﻿#include "ExprVisitor.h"
#include "global.h"
#include "exprvalue.h"
#include "cppapi.h"

#include <iostream>
#include <QString>
#include <PinLexer.h>
#include <QDateTime> 
#include <QDir>
#include <QRegularExpression>
//#include <QDebug>
#include <QCoreApplication>

#include "antlr4-runtime.h"
#include "PinErrListener.h"

using namespace antlr4;

//stName 结构的类型名称
int getMemIndexFromStruct(std::string stName, std::string paraName, antlr4::ParserRuleContext* ctx = nullptr);

extern int s_mainFunPara;

enum CALL_FUN_FALG
{
    NO_NEED_RETURN = 0x1, //不需要返回值
    NEED_RETURN = 0x2,//需要返回值
    NORMAL_FUN_CALL = 0x4,// 普通函数，即自己写的函数的调用
    CPP_FUN_CALL = 0x8,//调用底层的cpp函数
    MULTI_CALL_FUN = 0x10,//是不是开始多级调用。或者说是不是多级调用中的一级。
    //20250410 发现多级调用时，外面接收的函数参数、或者自动定义参数，要是最后一级的返回值，不能是中间级别的函数返回值。
    MULTI_CALL_LAST_CALL_FUN = 0x20,//多级调用的最后一级。如果是多级的最后一级，则设置该标记；
};

bool isSetFlag(int v, CALL_FUN_FALG flag)
{
    return (v & flag) != 0;
}

void Warnning(QString& msg)
{
    std::cout << msg.toStdString() << std::endl;
}

std::string getStructVarTypeName(SymNode* pSym)
{
    if(pSym->type == EXPR_STRUCT && pSym->value.vpoint != nullptr)
    {
        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
        return pValue->structType;
    }
    return pSym->name;//避免返回空，导致都为空相等。
}

std::string getStructVarTypeName(ExprValue& pSym)
{
    if(pSym.type == EXPR_STRUCT && pSym.value.vpoint != nullptr)
    {
        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym.value.vpoint;
        return pValue->structType;
    }
    return "";
}

//前面已经进行过类型对比了。
int FillSymNodeByExpr(SymNode* pSym, ExprValue& expr, antlr4::ParserRuleContext* ctx, bool iswarn=true, AssignOpType op = EQUAL_ASSIGN)
{
    int ret = EXPR_to_Err;
    int type  = (pSym->type << 16) | expr.type;

    switch(type)
    {
    case EXPR_STRING << 16 | EXPR_INT:
        ret = EXPR_Int_to_String;//整数转字符串，非法，下同
        if(iswarn)
        {
            std::cout << u8"错误:不能把整数值赋值给字符串类型" << pSym->name << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_String; //整数转字符串，非法，下同
        if(iswarn)
        {
            std::cout << u8"不能把长整数值赋值给字符串类型" << pSym->name << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_String; //整数转字符串，非法，下同
        if(iswarn)
        {
            std::cout << u8"不能把小数值赋值给字符串类型" << pSym->name << std::endl;
        }
        break;
    case EXPR_INT << 16 | EXPR_STRING:
        ret = EXPR_String_to_Int;
        if(iswarn)
        {
            std::cout << u8"不能把字符串赋值给整数类型" << pSym->name << std::endl;
        }
        //把字符串释放掉，避免内存泄漏
        expr.freeMem();
        break;
    case EXPR_INT64 << 16 | EXPR_STRING:
        ret = EXPR_String_to_Int64;
        if(iswarn)
        {
            std::cout << u8"不能把字符串赋值给长整数类型" << pSym->name << std::endl;
        }
        //把字符串是否掉，避免内存泄漏
        expr.freeMem();
        break;
    case EXPR_FLOAT << 16 | EXPR_STRING:
        ret = EXPR_String_to_Float;
        if(iswarn)
        {
            std::cout << u8"不能把字符串赋值给小数类型" << pSym->name << std::endl;
        }
        //把字符串是否掉，避免内存泄漏
        expr.freeMem();
        break;

        //下面是合法的，不过有些会精度丢失
    case EXPR_INT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = expr.value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= expr.value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= expr.value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += expr.value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= expr.value.vint;
            break;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int64;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = expr.value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= expr.value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= expr.value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += expr.value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= expr.value.vint;
            break;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Float;
        //pSym->value.vfloat = expr.value.vint;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = expr.value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= expr.value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= expr.value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += expr.value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= expr.value.vint;
            break;
        }
        break;

    case EXPR_INT64 << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int64;
        //pSym->value.vint64 = expr.value.vint64;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = expr.value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= expr.value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= expr.value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += expr.value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= expr.value.vint64;
            break;
        }
        break;
    case EXPR_INT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int;
        //pSym->value.vint = expr.value.vint64;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = expr.value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= expr.value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= expr.value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += expr.value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= expr.value.vint64;
            break;
        }
        if(iswarn)
        {
            if (expr.value.vint64 < std::numeric_limits<qint32>::min() || expr.value.vint64 > std::numeric_limits<qint32>::max())
            {
                QString msg = QString(u8"警告：长整数变量值 %1 赋值给整数类型变量%2，精度可能丢失，请注意检查值域范围!").arg(expr.value.vint64).arg(QStr(pSym->name));
                std::cout << msg.toStdString() << std::endl;
            }
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Float;
        //pSym->value.vfloat  = expr.value.vint64;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = expr.value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= expr.value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= expr.value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += expr.value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= expr.value.vint64;
            break;
        }
        break;

    case EXPR_FLOAT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Float;
        //pSym->value.vfloat = expr.value.vfloat;
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = expr.value.vfloat;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= expr.value.vfloat;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= expr.value.vfloat;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += expr.value.vfloat;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= expr.value.vfloat;
            break;
        }
        break;

    case EXPR_INT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int;
        //pSym->value.vint  = std::floor(expr.value.vfloat);
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = std::floor(expr.value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= std::floor(expr.value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= std::floor(expr.value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint += std::floor(expr.value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= std::floor(expr.value.vfloat);
            break;
        }
        if(iswarn)
        {
            //太多了。
            //std::cout << u8"小数赋值给整数类型，可能丢失精度" << pSym->name << std::endl;
        }
        break;
    case EXPR_INT << 16 | EXPR_CHAR:
        ret = EXPR_Char_to_Int;
        //pSym->value.vint  = std::floor(expr.value.vfloat);
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = expr.value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= expr.value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= expr.value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += expr.value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= expr.value.vint;
            break;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_CHAR:
        ret = EXPR_Char_to_Int64;
        //pSym->value.vint  = std::floor(expr.value.vfloat);
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = expr.value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= expr.value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= expr.value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += expr.value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= expr.value.vint;
            break;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int64;
        //pSym->value.vint64  = std::floor(expr.value.vfloat);
        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = std::floor(expr.value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= std::floor(expr.value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= std::floor(expr.value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += std::floor(expr.value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= std::floor(expr.value.vfloat);
            break;
        }
        if(iswarn)
        {
            std::cout << u8"小数赋值给长整数类型，可能丢失精度" << pSym->name << std::endl;
        }
        break;

    case EXPR_STRING << 16 | EXPR_STRING:

        switch(op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_String_to_String;

            if(pSym->value.vpoint != nullptr)
            {
                //先把老的释放掉
                pSym->destory();
            }
            //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
            pSym->value.vpoint  = expr.value.vpoint;
            expr.value.vpoint = nullptr;
            //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        }
            break;
        case ADD_ASSIGN:
            if(expr.value.vpoint != nullptr)
            {
                ret = EXPR_String_to_String;
                if(pSym->value.vpoint == nullptr)
                {

                    //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
                    pSym->value.vpoint  = expr.value.vpoint;
                    expr.value.vpoint = nullptr;
                }
                else
                {
                    //必须做深拷贝
                    ((QByteArray*)pSym->value.vpoint)->append(*(QByteArray*)(expr.value.vpoint));
                    //expr中的不释放，外面会释放。统一释放
                    expr.freeMem();
                }
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if(iswarn)
            {
                std::cout << u8"字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }

        break;

    case EXPR_U16STRING << 16 | EXPR_U16STRING:
    {

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_U16String_to_U16String;

            if (pSym->value.vpoint != nullptr)
            {
                //先把老的释放掉
                pSym->destory();
            }
            //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
            pSym->value.vpoint = expr.value.vpoint;
            expr.value.vpoint = nullptr;
            //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        }
        break;
        case ADD_ASSIGN:
            if (expr.value.vpoint != nullptr)
            {
                ret = EXPR_U16String_to_U16String;
                if (pSym->value.vpoint == nullptr)
                {

                    //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
                    pSym->value.vpoint = expr.value.vpoint;
                    expr.value.vpoint = nullptr;
                }
                else
                {
                    //必须做深拷贝
                    ((QString*)pSym->value.vpoint)->append(*(QString*)(expr.value.vpoint));
                    //expr中的不释放，外面会释放。统一释放
                    expr.freeMem();
                }
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if (iswarn)
            {
                std::cout << u8"字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }
    }
        break;

    case EXPR_U16STRING << 16 | EXPR_STRING:

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_String_to_U16String;

            if (pSym->value.vpoint == nullptr)
            {
                pSym->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            else
            {
                //先把老的释放掉
                ((QString*)pSym->value.vpoint)->clear();
            }

            //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
            ((QString*)pSym->value.vpoint)->append(*(QByteArray*)expr.value.vpoint);
            expr.freeMem();
            //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        }
        break;
        case ADD_ASSIGN:
            if (expr.value.vpoint != nullptr)
            {
                ret = EXPR_String_to_U16String;
                if (pSym->value.vpoint == nullptr)
                {
                    pSym->value.vpoint = new QString(*(QByteArray*)(expr.value.vpoint));
                    #ifdef PIN_MEM_REF
                        newTime();
                    #endif
                }
                else
                {
                    //必须做深拷贝
                    ((QString*)pSym->value.vpoint)->append(*(QByteArray*)(expr.value.vpoint));
                }
                expr.freeMem();
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if (iswarn)
            {
                std::cout << u8"U16字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }

        break;
    case EXPR_BOOL << 16 | EXPR_BOOL:
        ret = EXPR_Bool_to_Bool;
        pSym->value.vbool = expr.value.vbool;
        break;
    case EXPR_STRUCT << 16 | EXPR_STRUCT:
        if(EQUAL_ASSIGN == op)
        {
            //结构体表达式赋值。注意这样要深拷贝，否则会导致原来对象本身被修改
            ret = EXPR_Struct_to_Struct;

            //把老的释放
            pSym->destory();

            pSym->value.vpoint = expr.value.vpoint;
            expr.value.vpoint = nullptr;

            //深拷贝一下
            //STRUCT_VALUE_DATA* pSv = (STRUCT_VALUE_DATA*)expr.value.vpoint;
            //pSym->value.vpoint = pSv->deepCopy();
            //这里没有和字符串、时间保持一致，是深拷贝。总的说深拷贝肯定没有安全问题。
            //浅拷贝要保证该右值表达式变量是一次性使用。
        }
        else
        {
            if(iswarn)
            {
                std::cout << u8"结构体变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
        }
        break;
    case EXPR_LIST << 16 | EXPR_LIST: //这个可能压根不调用，直接在赋值语句里面手动做了。
    {
        //处理列表赋值，即表达式赋值给符号变量。这里使用浅拷贝，符号变量和表达式公用一份列表内存空间。
        //这里目前用在函数参数的传递处，列表是以传递引用的方式来传递。
        ret = EXPR_List_to_List;

        //把老的释放
        pSym->destory();

        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;

        //一减一加，正好不使用调整引用计数。
        //addListMapRefNum(pSym->value.vpoint);
    }
        break;
    case EXPR_MAP << 16 | EXPR_MAP:
    {
        //处理列表赋值，即表达式赋值给符号变量。这里使用浅拷贝，符号变量和表达式公用一份列表内存空间。
        //这里目前用在函数参数的传递处，列表是以传递引用的方式来传递。
        ret = EXPR_Map_to_Map;

        //把老的释放
        pSym->destory();

        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;

        //addListMapRefNum(pSym->value.vpoint);
    }
        break;
    case EXPR_FILE << 16 | EXPR_FILE:
    {
        //处理列表赋值，即表达式赋值给符号变量。这里使用浅拷贝，符号变量和表达式公用一份列表内存空间。
        //这里目前用在函数参数的传递处，列表是以传递引用的方式来传递。
        ret = EXPR_File_to_File;

        //把老的释放
        pSym->destory();

        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;

        //addListMapRefNum(pSym->value.vpoint);
    }
    break;
    case EXPR_EXCEL << 16 | EXPR_EXCEL:
    {
        //处理列表赋值，即表达式赋值给符号变量。这里使用浅拷贝，符号变量和表达式公用一份列表内存空间。
        //这里目前用在函数参数的传递处，列表是以传递引用的方式来传递。
        ret = EXPR_Excel_to_Excel;

        //把老的释放
        pSym->destory();

        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;

        //addListMapRefNum(pSym->value.vpoint);
    }
    break;
    case EXPR_DATE << 16 | EXPR_DATE:
    {
        //暂时和字符串表达式保持一致。
        ret = EXPR_Date_to_Date;

        //把老的释放
        pSym->destory();

        //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;
        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。

    }
    break;
    case EXPR_FUN << 16 | EXPR_FUN:
    case EXPR_CALL_BACK_FUN << 16 | EXPR_FUN:
    case EXPR_CALL_BACK_FUN << 16 | EXPR_CALL_BACK_FUN:
    {
        ret = EXPR_Fun_to_Fun;
        //函数给函数
        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;
        //后续如果发现这里会一个表达式，多
    }
        break;
    case EXPR_FUN << 16 | EXPR_MEMFUN:
    {
        //函数给函数
        ret = EXPR_MemFun_to_Fun;
        pSym->type = EXPR_MEMFUN; //注意修改一下函数类型
        pSym->value.vpoint = expr.value.vpoint;
        expr.value.vpoint = nullptr;
        //后续如果发现这里会一个表达式，多
    }
        break;

    case EXPR_CHAR << 16 | EXPR_CHAR:
    {
        ret = EXPR_Char_to_Char;
        pSym->type = EXPR_CHAR;
        pSym->value.vchar = expr.value.vchar;
    }
        break;

    case EXPR_WCHAR << 16 | EXPR_WCHAR:
    {
        ret = EXPR_WChar_to_WChar;
        pSym->type = EXPR_WCHAR;
        pSym->value.vwchar = expr.value.vwchar;
    }
    break;

    case EXPR_WCHAR << 16 | EXPR_CHAR:
    {
        ret = EXPR_Char_to_WChar;
        pSym->type = EXPR_WCHAR;
        pSym->value.vwchar = expr.value.vchar;
    }
    break;

    case EXPR_CHAR << 16 | EXPR_INT:
    {
        if(op == EQUAL_ASSIGN)
        {

            if(expr.value.vint <= 255 && expr.value.vint >= 0)
            {
                ret = EXPR_Int_to_Char;
                pSym->type = EXPR_CHAR;
                pSym->value.vchar = expr.value.vint;

            }
            else
            {
                std::cout << u8"整数给字符变量赋值，整数范围必须是0-255 " << std::endl;
            }
        }
    }
        break;

    case EXPR_WCHAR << 16 | EXPR_INT:
    {
        if (op == EQUAL_ASSIGN)
        {
            if (expr.value.vint <= 65535 && expr.value.vint >= 0)
            {
                ret = EXPR_Int_to_WChar;
                pSym->type = EXPR_WCHAR;
                pSym->value.vwchar = expr.value.vint;
            }
            else
            {
                std::cout << u8"整数给U16字符变量赋值，整数范围必须是0-65535 " << std::endl;
            }
        }
    }
    break;

    case EXPR_STRING << 16 | EXPR_CHAR:
    {
        pSym->type = EXPR_STRING;

        switch(op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_Char_to_String;

            if (pSym->value.vpoint != nullptr)
            {
                ((QByteArray*)pSym->value.vpoint)->clear();
            }
            else
            {
                pSym->value.vpoint = new QByteArray;
#ifdef PIN_MEM_REF
                newTime();
#endif
            }

            ((QByteArray*)pSym->value.vpoint)->append(expr.value.vchar);

        }
            break;
        case ADD_ASSIGN:
            if(expr.value.vpoint != nullptr)
            {
                ret = EXPR_Char_to_String;

                if(pSym->value.vpoint == nullptr)
                {

                    //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
                    QByteArray* pData = new QByteArray();
        #ifdef PIN_MEM_REF
                    newTime();
        #endif
                    pData->append(expr.value.vchar);
                }
                else
                {
                    //必须做深拷贝
                    ((QByteArray*)pSym->value.vpoint)->append(expr.value.vchar);
                    //expr中的不释放，外面会释放。
                }
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if(iswarn)
            {
                std::cout << u8"字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }
    }
        break;

    case EXPR_U16STRING << 16 | EXPR_CHAR:
    {
        pSym->type = EXPR_U16STRING;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_Char_to_U16String;

            if (pSym->value.vpoint != nullptr)
            {
                ((QString*)pSym->value.vpoint)->clear();
            }
            else
            {
                pSym->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }

            ((QString*)pSym->value.vpoint)->append(QChar(expr.value.vchar));

        }
        break;
        case ADD_ASSIGN:
            if (expr.value.vpoint != nullptr)
            {
                if (pSym->value.vpoint == nullptr)
                {
                    ret = EXPR_Char_to_U16String;
                    //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
                    QString* pData = new QString();
#ifdef PIN_MEM_REF
                    newTime();
#endif
                    pData->append(QChar(expr.value.vchar));
                }
                else
                {
                    //必须做深拷贝
                    ((QString*)pSym->value.vpoint)->append(QChar(expr.value.vchar));
                    //expr中的不释放，外面会释放。
                }
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if (iswarn)
            {
                std::cout << u8"U16字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }
    }
    break;

    case EXPR_U16STRING << 16 | EXPR_WCHAR:
    {
        pSym->type = EXPR_U16STRING;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_WChar_to_U16String;

            if (pSym->value.vpoint != nullptr)
            {
                ((QString*)pSym->value.vpoint)->clear();
            }
            else
            {
                pSym->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }

            ((QString*)pSym->value.vpoint)->append(QChar(expr.value.vwchar));
        }
        break;
        case ADD_ASSIGN:
            if (expr.value.vpoint != nullptr)
            {
                if (pSym->value.vpoint == nullptr)
                {
                    ret = EXPR_Char_to_U16String;
                    //注意这里是浅拷贝，认定表达式每次都是独立求取的，不会多次赋值给其它。
                    QString* pData = new QString();
#ifdef PIN_MEM_REF
                    newTime();
#endif
                    pData->append(QChar(expr.value.vwchar));
                }
                else
                {
                    //必须做深拷贝
                    ((QString*)pSym->value.vpoint)->append(QChar(expr.value.vwchar));
                    //expr中的不释放，外面会释放。
                }
            }
            break;
        case MUL_ASSIGN:
        case DIV_ASSIGN:
        case SUB_ASSIGN:
            if (iswarn)
            {
                std::cout << u8"U16字符串变量无法进行-= *= /=操作！" << pSym->name << std::endl;
            }
            break;
        }
    }
    break;

    default:
        break;
    }
    if(iswarn && ret < 0)
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 的类型是 %4 , 其赋值类型是 %5， 二者无法匹配！请检查。").arg(curLine).arg(curStatement).arg(QStr(pSym->name))
            .arg(getVarTypeNameByName(pSym->name,ctx)).arg(getExpeTypeValue(expr.type,&expr));
        std::cout << msg.toStdString() << std::endl;
    }

    return ret;
}


//判断可以对比，0 相等 -1小于 1 大于。-100：非法不能对比。给出对比结果
int CompareSymNodeAndExpr(SymNode* pSym, ExprValue& expr, bool iswarn = true)
{
    int ret = CAN_NOT_CMP;
    int type = (pSym->type << 16) | expr.type;

    switch (type)
    {
    case EXPR_STRING << 16 | EXPR_INT64:
    case EXPR_STRING << 16 | EXPR_INT:
    case EXPR_INT << 16 | EXPR_STRING:
    case EXPR_INT64 << 16 | EXPR_STRING:
    case EXPR_U16STRING << 16 | EXPR_INT64:
    case EXPR_U16STRING << 16 | EXPR_INT:
    case EXPR_INT << 16 | EXPR_U16STRING:
    case EXPR_INT64 << 16 | EXPR_U16STRING:
        if (iswarn)
        {
            std::cout << u8"字符串和整数不能进行逻辑比对大小运算" << pSym->name << std::endl;
        }
        break;


    case EXPR_STRING << 16 | EXPR_FLOAT:
    case EXPR_FLOAT << 16 | EXPR_STRING:
    case EXPR_U16STRING << 16 | EXPR_FLOAT:
    case EXPR_FLOAT << 16 | EXPR_U16STRING:
        if (iswarn)
        {
            std::cout << u8"字符串和小数不能进行逻辑比对大小运算" << pSym->name << std::endl;
        }
        break;

    //整数和整数对比
    case EXPR_INT << 16 | EXPR_INT:
        ret = (pSym->value.vint == expr.value.vint) ? EQUAL_STATUS : ((pSym->value.vint > expr.value.vint)? GREATER_STATUS: LESS_STATUS);
        break;

    case EXPR_INT64 << 16 | EXPR_INT:
        ret = (pSym->value.vint64 == expr.value.vint) ? EQUAL_STATUS : ((pSym->value.vint64 > expr.value.vint) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_FLOAT << 16 | EXPR_INT:
        ret = (pSym->value.vfloat == expr.value.vint) ? EQUAL_STATUS : ((pSym->value.vfloat > expr.value.vint) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_INT64 << 16 | EXPR_INT64:
        ret = (pSym->value.vint64 == expr.value.vint64) ? EQUAL_STATUS : ((pSym->value.vint64 > expr.value.vint64) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_INT << 16 | EXPR_INT64:
        ret = (pSym->value.vint == expr.value.vint64) ? EQUAL_STATUS : ((pSym->value.vint > expr.value.vint64) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_FLOAT << 16 | EXPR_INT64:
        ret = (pSym->value.vfloat == expr.value.vint64) ? EQUAL_STATUS : ((pSym->value.vfloat > expr.value.vint64) ? GREATER_STATUS : LESS_STATUS);
        break;

    //这里可能有误差，浮点数默认是不能进行等于判断的，需要使用abs
    case EXPR_FLOAT << 16 | EXPR_FLOAT:
        ret = (pSym->value.vfloat == expr.value.vfloat) ? EQUAL_STATUS : ((pSym->value.vfloat > expr.value.vfloat) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_INT << 16 | EXPR_FLOAT:
        ret = (pSym->value.vint == expr.value.vfloat) ? EQUAL_STATUS : ((pSym->value.vint > expr.value.vfloat) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_INT64 << 16 | EXPR_FLOAT:
        ret = (pSym->value.vint64 == expr.value.vfloat) ? EQUAL_STATUS : ((pSym->value.vint64 > expr.value.vfloat) ? GREATER_STATUS : LESS_STATUS);
        break;

    case EXPR_STRING << 16 | EXPR_STRING:

        //都是空
        if (pSym->value.vpoint == nullptr && expr.value.vpoint == nullptr)
        {
            ret = EQUAL_STATUS;
        }
        else if (pSym->value.vpoint != nullptr && expr.value.vpoint != nullptr)
        {
            QString exprStr(*(QByteArray*)expr.value.vpoint);
            if (((QByteArray*)pSym->value.vpoint)->operator==(exprStr))
            {
                ret = EQUAL_STATUS;
            }
            else if (((QByteArray*)pSym->value.vpoint)->operator>(exprStr))
            {
                ret = GREATER_STATUS;
            }
            else
            {
                ret = LESS_STATUS;
            }
        }
        else
        {
            //不空的为大
            ret = ((pSym->value.vpoint != nullptr) ? GREATER_STATUS : LESS_STATUS);
        }
        break;

    case EXPR_U16STRING << 16 | EXPR_U16STRING:

        //都是空
        if (pSym->value.vpoint == nullptr && expr.value.vpoint == nullptr)
        {
            ret = EQUAL_STATUS;
        }
        else if (pSym->value.vpoint != nullptr && expr.value.vpoint != nullptr)
        {
            QString exprStr(*(QString*)expr.value.vpoint);
            int v = ((QString*)pSym->value.vpoint)->compare(exprStr);

            if(0 == v)
            {
                ret = EQUAL_STATUS;
            }
            else
            {
                ret = ((v > 0) ? GREATER_STATUS : LESS_STATUS);
            }
        }
        else
        {
            //不空的为大
            ret = ((pSym->value.vpoint != nullptr) ? GREATER_STATUS : LESS_STATUS);
        }
        break;
    default:
        //统一视作不能对比。
        if (iswarn)
        {
            QString msg = QString(u8"变量 %1 和表达式只 %2 不能进行类型对比").arg(QString::fromStdString(pSym->name)).arg(expr.toString());
            std::cout << msg.toStdString() << std::endl;
        }
        break;
    }

    return ret;
}


//和FillSymNodeByExpr类似，不过是变量赋值变量
//pSym = pSrcSyn;
int FillSymNodeBySymNode(SymNode* pSym, SymNode* pSrcSyn, bool iswarn = true)
{

    int ret = EXPR_to_Err;
    int type = (pSym->type << 16) | pSrcSyn->type;

    switch (type)
    {
    case EXPR_STRING << 16 | EXPR_INT:
    case EXPR_U16STRING << 16 | EXPR_INT:
    {
        ret = EXPR_Int_to_String;//整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把整数值赋值给字符串类型" << pSym->name << std::endl;
        }
    }
        break;
    case EXPR_STRING << 16 | EXPR_INT64:
    case EXPR_U16STRING << 16 | EXPR_INT64:
    {
        ret = EXPR_Int64_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把长整数值赋值给字符串类型" << pSym->name << std::endl;
        }
    }
        break;
    case EXPR_STRING << 16 | EXPR_FLOAT:
    case EXPR_U16STRING << 16 | EXPR_FLOAT:
    {
        ret = EXPR_Float_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把小数值赋值给字符串类型" << pSym->name << std::endl;
        }
    }
        break;
    case EXPR_INT << 16 | EXPR_STRING:
    case EXPR_INT << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Int;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给整数类型" << pSym->name << std::endl;
        }
    }
        break;
    case EXPR_INT64 << 16 | EXPR_STRING:
    case EXPR_INT64 << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Int64;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给长整数类型" << pSym->name << std::endl;
        }
    }
        break;
    case EXPR_FLOAT << 16 | EXPR_STRING:
    case EXPR_FLOAT << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Float;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给小数类型" << pSym->name << std::endl;
        }
    }
        break;

        //下面是合法的，不过有些会精度丢失
    case EXPR_INT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int;
        pSym->value.vint = pSrcSyn->value.vint;
        break;
    case EXPR_INT64 << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int64;
        pSym->value.vint64 = pSrcSyn->value.vint;
        break;
    case EXPR_FLOAT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Float;
        pSym->value.vfloat = pSrcSyn->value.vint;
        break;

    case EXPR_INT64 << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int64;
        pSym->value.vint64 = pSrcSyn->value.vint64;
        break;
    case EXPR_INT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int;
        pSym->value.vint = pSrcSyn->value.vint64;
        if (iswarn)
        {
            QString msg = QString(u8"警告：长整数变量 %1 值 %2 赋值给整数类型变量 %3，精度可能丢失，请注意检查值域范围!").arg(QStr(pSrcSyn->name)).arg(pSrcSyn->value.vint64).arg(QStr(pSym->name));
            std::cout << msg.toStdString() << std::endl;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Float;
        pSym->value.vfloat = pSrcSyn->value.vint64;
        break;

    case EXPR_FLOAT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Float;
        pSym->value.vfloat = pSrcSyn->value.vfloat;
        break;

    case EXPR_INT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int;
        pSym->value.vint = std::floor(pSrcSyn->value.vfloat);
        if (iswarn)
        {
            //std::cout << u8"小数赋值给整数类型，可能丢失精度" << pSym->name << std::endl;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int64;
        pSym->value.vint64 = std::floor(pSrcSyn->value.vfloat);
        if (iswarn)
        {
            std::cout << u8"小数赋值给长整数类型，可能丢失精度" << pSym->name << std::endl;
        }
        break;
    case EXPR_CHAR << 16 | EXPR_CHAR:
        ret = EXPR_Char_to_Char;
        pSym->value.vchar = pSrcSyn->value.vchar;
        break;
    case EXPR_WCHAR << 16 | EXPR_WCHAR:
        ret = EXPR_WChar_to_WChar;
        pSym->value.vwchar = pSrcSyn->value.vwchar;
        break;
    case EXPR_WCHAR << 16 | EXPR_CHAR:
        ret = EXPR_Char_to_WChar;
        pSym->value.vwchar = pSrcSyn->value.vchar;
        break;
    case EXPR_STRING << 16 | EXPR_STRING:
        ret = EXPR_String_to_String;
        //注意这里是深拷贝，两个字符串赋值彼此独立
        if (pSrcSyn->value.vpoint != nullptr)
        {
            //原来的值要释放
            if (pSym->value.vpoint != nullptr)
            {
                delete (QBitArray*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            pSym->value.vpoint = new QBitArray(*(QBitArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            pSym->value.vpoint = nullptr;
        }

        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        break;
    case EXPR_U16STRING << 16 | EXPR_U16STRING:
        ret = EXPR_String_to_String;
        //注意这里是深拷贝，两个字符串赋值彼此独立
        if (pSrcSyn->value.vpoint != nullptr)
        {
            //原来的值要释放
            if (pSym->value.vpoint != nullptr)
            {
                delete (QString*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            pSym->value.vpoint = new QString(*(QString*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            pSym->value.vpoint = nullptr;
        }

        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        break;
    case EXPR_U16STRING << 16 | EXPR_STRING:
        ret = EXPR_String_to_U16String;
        //注意这里是深拷贝，两个字符串赋值彼此独立
        if (pSrcSyn->value.vpoint != nullptr)
        {
            //原来的值要释放
            if (pSym->value.vpoint != nullptr)
            {
                delete (QString*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            pSym->value.vpoint = new QString(*(QByteArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            pSym->value.vpoint = nullptr;
        }

        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        break;
    case EXPR_BOOL <<16 | EXPR_BOOL:
        ret = EXPR_Bool_to_Bool;
        pSym->value.vbool = pSrcSyn->value.vbool;
        break;
    case EXPR_STRUCT <<16 | EXPR_STRUCT:
    {
        ret = EXPR_Struct_to_Struct;

        if (pSym->value.vpoint != nullptr)
        {
            STRUCT_VALUE_DATA* pData = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
            pData->destory();

            delete (STRUCT_VALUE_DATA*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
        }

        STRUCT_VALUE_DATA* pSv = (STRUCT_VALUE_DATA*)pSrcSyn->value.vpoint;
        pSym->value.vpoint = pSv->deepCopy();
    }
        break;

    case EXPR_LIST <<16 | EXPR_LIST:
    {
        ret = EXPR_List_to_List;

        //旧值要先释放或解除引用
        pSym->destory();

        //改成浅拷贝
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        addListMapRefNum(pSrcSyn->value.vpoint);
    }
        break;

    case EXPR_MAP <<16 | EXPR_MAP:
    {
        ret = EXPR_Map_to_Map;
#if 0
        std::unordered_map<ExprValue_, ExprValue_*>* pData = (std::unordered_map<ExprValue_, ExprValue_*>*)pSrcSyn->value.vpoint;

        std::unordered_map<ExprValue_, ExprValue_*>* pNew = new std::unordered_map<ExprValue_, ExprValue_*>();


        for (std::unordered_map<ExprValue_, ExprValue_*>::iterator it = pData->begin(); it != pData->end(); ++it)
        {
            ExprValue_ key = it->first;
            ExprValue_* v = it->second->deepCopy2();

            (*pNew)[key] = v;
        }

        pSym->value.vpoint = pNew;
#endif
        pSym->destory();
        //改成浅拷贝
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        addListMapRefNum(pSrcSyn->value.vpoint);
    }
        break;
    case EXPR_FILE << 16 | EXPR_FILE:
    {
        ret = EXPR_File_to_File;

        pSym->destory();
        //改成浅拷贝
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        addListMapRefNum(pSrcSyn->value.vpoint);
    }
    break;
    case EXPR_EXCEL << 16 | EXPR_EXCEL:
    {
        ret = EXPR_Excel_to_Excel;

        pSym->destory();
        //改成浅拷贝
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        addListMapRefNum(pSrcSyn->value.vpoint);
    }
    break;
    case EXPR_DATE << 16 | EXPR_DATE:
    {
        ret = EXPR_Date_to_Date;
        //注意这里是深拷贝，两个日期赋值彼此独立
        if (pSrcSyn->value.vpoint != nullptr)
        {
            if (pSym->value.vpoint != nullptr)
            {
                delete (QDateTime*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            pSym->value.vpoint = new QDateTime(*(QDateTime*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            pSym->value.vpoint = nullptr;
        }
    }
    break;
    default:
        break;
    }
    if (iswarn && ret < 0)
    {
        std::cout << pSym->name << u8"变量的类型和其赋值无法匹配！请检查。" << std::endl;
    }

    return ret;
}


//表达式赋值
int FillExprByExpr(ExprValue* pSym, ExprValue* pSrcSyn, antlr4::ParserRuleContext *ctx, bool iswarn, AssignOpType op)
{

    int ret = EXPR_to_Err;
    int type = (pSym->type << 16) | pSrcSyn->type;

    switch (type)
    {
    case EXPR_STRING << 16 | EXPR_INT:
    case EXPR_U16STRING << 16 | EXPR_INT:
    {
        ret = EXPR_Int_to_String;//整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把整数值赋值给字符串类型" << std::endl;
        }
    }
        break;
    case EXPR_STRING << 16 | EXPR_INT64:
    case EXPR_U16STRING << 16 | EXPR_INT64:
    {
        ret = EXPR_Int64_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把长整数值赋值给字符串类型" << std::endl;
        }
    }
        break;
    case EXPR_STRING << 16 | EXPR_FLOAT:
    case EXPR_U16STRING << 16 | EXPR_FLOAT:
    {
        ret = EXPR_Float_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把小数值赋值给字符串类型" << std::endl;
        }
    }
        break;
    case EXPR_INT << 16 | EXPR_STRING:
    case EXPR_INT << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Int;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给整数类型" << std::endl;
        }
    }
        break;
    case EXPR_INT64 << 16 | EXPR_STRING:
    case EXPR_INT64 << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Int64;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给长整数类型" << std::endl;
        }
    }
        break;
    case EXPR_FLOAT << 16 | EXPR_STRING:
    case EXPR_FLOAT << 16 | EXPR_U16STRING:
    {
        ret = EXPR_String_to_Float;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给小数类型" << std::endl;
        }
    }
        break;

        //下面是合法的，不过有些会精度丢失
    case EXPR_INT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= pSrcSyn->value.vint;
            break;
        }

        break;
    case EXPR_INT64 << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= pSrcSyn->value.vint;
            break;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vint;
            break;
        }
        break;

    case EXPR_INT64 << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= pSrcSyn->value.vint64;
            break;
        }
        break;
    case EXPR_INT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= pSrcSyn->value.vint64;
            break;
        }
        if (iswarn)
        {
            std::cout << u8"警告：长整数赋值给整数类型，可能丢失精度" << std::endl;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vint64;
            break;
        }
        break;

    case EXPR_FLOAT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vfloat;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vfloat;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vfloat;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vfloat;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vfloat;
            break;
        }
        break;

    case EXPR_INT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int;
        pSym->value.vint = std::floor(pSrcSyn->value.vfloat);

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = std::floor(pSrcSyn->value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= std::floor(pSrcSyn->value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= std::floor(pSrcSyn->value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint += std::floor(pSrcSyn->value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= std::floor(pSrcSyn->value.vfloat);
            break;
        }
        if (iswarn)
        {
            //std::cout << u8"小数赋值给整数类型，可能丢失精度"  << std::endl;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = std::floor(pSrcSyn->value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= std::floor(pSrcSyn->value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= std::floor(pSrcSyn->value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += std::floor(pSrcSyn->value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= std::floor(pSrcSyn->value.vfloat);
            break;
        }
        if (iswarn)
        {
            std::cout << u8"小数赋值给长整数类型，可能丢失精度" << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_STRING:
    {
        ret = EXPR_String_to_String;

            switch(op)
            {
            case EQUAL_ASSIGN:
            {
                //注意这里是浅拷贝，两个字符串赋值彼此独立。把原来的释放掉
                if (pSym->value.vpoint != nullptr)
                {
                    delete (QByteArray*)pSym->value.vpoint;
					#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }
                pSym->value.vpoint = pSrcSyn->value.vpoint;
                pSrcSyn->value.vpoint = nullptr;
            }
                break;
            case MUL_ASSIGN:
            case SUB_ASSIGN:
            case DIV_ASSIGN:
                break;
            case ADD_ASSIGN:
            {
                if (pSrcSyn->value.vpoint != nullptr)
                {
                    if (pSym->value.vpoint != nullptr)
                    {
                        ((QByteArray*)pSym->value.vpoint)->append(*(QByteArray*)pSrcSyn->value.vpoint);
                    }
                    else
                    {
                        //这里是浅拷贝，反正外面每次expr都要析构释放。
                        //每次获取表达式都是深拷贝的一个对象值，理论上这里直接掏空该对象，是完全合法的。
                        pSym->value.vpoint = pSrcSyn->value.vpoint;
                        pSrcSyn->value.vpoint = nullptr;
                    }
                }
            }
                break;
            }

    }
        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        break;
    case EXPR_U16STRING << 16 | EXPR_U16STRING:
    {
        ret = EXPR_U16String_to_U16String;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            //注意这里是浅拷贝，两个字符串赋值彼此独立。把原来的释放掉
            if (pSym->value.vpoint != nullptr)
            {
                delete (QString*)pSym->value.vpoint;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            pSym->value.vpoint = pSrcSyn->value.vpoint;
            pSrcSyn->value.vpoint = nullptr;
        }
        break;
        case MUL_ASSIGN:
        case SUB_ASSIGN:
        case DIV_ASSIGN:
            break;
        case ADD_ASSIGN:
        {
            if (pSrcSyn->value.vpoint != nullptr)
            {
                if (pSym->value.vpoint != nullptr)
                {
                    ((QString*)pSym->value.vpoint)->append(*(QString*)pSrcSyn->value.vpoint);
                }
                else
                {
                    //这里是浅拷贝，反正外面每次expr都要析构释放。
                    //每次获取表达式都是深拷贝的一个对象值，理论上这里直接掏空该对象，是完全合法的。
                    pSym->value.vpoint = pSrcSyn->value.vpoint;
                    pSrcSyn->value.vpoint = nullptr;
                }
            }
        }
        break;
        }

    }
    //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
    break;

    case EXPR_U16STRING << 16 | EXPR_STRING:
    {
        ret = EXPR_String_to_U16String;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            if (pSym->value.vpoint == nullptr)
            {
                pSym->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            else
            {
                //注意这里是浅拷贝，两个字符串赋值彼此独立。把原来的清空
                ((QString*)pSym->value.vpoint)->clear();
            }
            ((QString*)pSym->value.vpoint)->append(*(QByteArray*)pSrcSyn->value.vpoint);
            pSrcSyn->freeMem();
        }
        break;
        case MUL_ASSIGN:
        case SUB_ASSIGN:
        case DIV_ASSIGN:
            break;
        case ADD_ASSIGN:
        {
            if (pSrcSyn->value.vpoint != nullptr)
            {
                if (pSym->value.vpoint != nullptr)
                {
                    ((QString*)pSym->value.vpoint)->append(*(QByteArray*)pSrcSyn->value.vpoint);
                }
                else
                {
                    pSym->value.vpoint = new QString(*(QByteArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
                    newTime();
#endif
                    pSrcSyn->freeMem();
                }
            }
        }
        break;
        }

    }
    //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
    break;
    case EXPR_BOOL <<16 | EXPR_BOOL:
        ret = EXPR_Bool_to_Bool;
        pSym->value.vbool = pSrcSyn->value.vbool;
        break;
        //没有结构赋值结构，该函数只在基本变量赋值中使用。

    case EXPR_DATE <<16 | EXPR_DATE:
        ret = EXPR_Date_to_Date;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;
        break;

    case EXPR_FILE <<16 | EXPR_FILE:
        ret = EXPR_File_to_File;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;
        break;

    case EXPR_EXCEL << 16 | EXPR_EXCEL:
        ret = EXPR_Excel_to_Excel;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;
        break;

    case EXPR_FILE <<16 | EXPR_STRING:
    {
        ret = EXPR_String_to_File;
        pSym->freeMem();

        if(pSrcSyn->value.vpoint != nullptr)
        {
            FILE_VALUE_DATA* pFileData = new FILE_VALUE_DATA();

            QString filePath(*(QByteArray*)pSrcSyn->value.vpoint);

            pFileData->pFileInfo = new QFileInfo(filePath);

    #ifdef PIN_MEM_REF
            newTime(2);
    #endif

            pSym->value.vpoint = pFileData;

            addListMapRefNum(pFileData);

            //这里是个特例，EXPR_STRING需要释放。因为前面都是做转移，而这里则需要释放
            //暂时保持一致，其实还是外部释放好一点
            pSrcSyn->freeMem();
        }

    }
        break;

    case EXPR_LIST << 16 | EXPR_LIST:
    {
        ret = EXPR_List_to_List;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;

        //不用加减计数，一来一去，正好持平
    }
        break;

    case EXPR_MAP << 16 | EXPR_MAP:
    {
        ret = EXPR_Map_to_Map;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;

        //不用加减计数，一来一去，正好持平
    }
    break;

    case EXPR_STRUCT << 16 | EXPR_STRUCT:
    {
        ret = EXPR_Struct_to_Struct;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;
    }
    break; 

    case EXPR_STRUCT_DEC << 16 | EXPR_STRUCT_DEC:
    {
        ret = EXPR_StructDesc_to_StructDesc;
        pSym->freeMem();
        pSym->value.vpoint = pSrcSyn->value.vpoint;
        pSrcSyn->value.vpoint = nullptr;
    }
    break;

    case EXPR_CHAR << 16 | EXPR_CHAR:
    {
        ret = EXPR_Char_to_Char;
        //pSym->freeMem();
        pSym->value.vchar = pSrcSyn->value.vchar;
        //pSrcSyn->value.vpoint = nullptr;
    }
        break;

    case EXPR_WCHAR << 16 | EXPR_WCHAR:
    {
        ret = EXPR_WChar_to_WChar;
        //pSym->freeMem();
        pSym->value.vwchar = pSrcSyn->value.vwchar;
        //pSrcSyn->value.vpoint = nullptr;
    }
    break;

    case EXPR_WCHAR << 16 | EXPR_CHAR:
    {
        ret = EXPR_Char_to_WChar;
        //pSym->freeMem();
        pSym->value.vwchar = pSrcSyn->value.vchar;
        //pSrcSyn->value.vpoint = nullptr;
    }
    break;

    default:
        break;
    }
    if (ret < 0)
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 变量的类型和其赋值无法匹配！请检查。").arg(curLine).arg(curStatement);
        AbortException(msg);
    }

    return ret;
}


//表达式赋值
int FillExprBySymNode(ExprValue* pSym, SymNode* pSrcSyn, antlr4::ParserRuleContext *ctx, bool iswarn = true, AssignOpType op = EQUAL_ASSIGN)
{

    int ret = EXPR_to_Err;
    int type = (pSym->type << 16) | pSrcSyn->type;

    switch (type)
    {
    case EXPR_STRING << 16 | EXPR_INT:
        ret = EXPR_Int_to_String;//整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把整数值赋值给字符串类型"  << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把长整数值赋值给字符串类型" << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_String; //整数转字符串，非法，下同
        if (iswarn)
        {
            std::cout << u8"不能把小数值赋值给字符串类型"  << std::endl;
        }
        break;
    case EXPR_INT << 16 | EXPR_STRING:
        ret = EXPR_String_to_Int;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给整数类型" << std::endl;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_STRING:
        ret = EXPR_String_to_Int64;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给长整数类型" << std::endl;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_STRING:
        ret = EXPR_String_to_Float;
        if (iswarn)
        {
            std::cout << u8"不能把字符串赋值给小数类型" << std::endl;
        }
        break;

        //下面是合法的，不过有些会精度丢失
    case EXPR_INT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= pSrcSyn->value.vint;
            break;
        }

        break;
    case EXPR_INT64 << 16 | EXPR_INT:
        ret = EXPR_Int_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= pSrcSyn->value.vint;
            break;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT:
        ret = EXPR_Int_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vint;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vint;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vint;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vint;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vint;
            break;
        }
        break;

    case EXPR_INT64 << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= pSrcSyn->value.vint64;
            break;
        }
        break;
    case EXPR_INT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Int;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vint += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= pSrcSyn->value.vint64;
            break;
        }
        if (iswarn)
        {
            std::cout << u8"警告：长整数赋值给整数类型，可能丢失精度" << std::endl;
        }
        break;
    case EXPR_FLOAT << 16 | EXPR_INT64:
        ret = EXPR_Int64_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vint64;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vint64;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vint64;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vint64;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vint64;
            break;
        }
        break;

    case EXPR_FLOAT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Float;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vfloat = pSrcSyn->value.vfloat;
            break;
        case MUL_ASSIGN:
            pSym->value.vfloat *= pSrcSyn->value.vfloat;
            break;
        case DIV_ASSIGN:
            pSym->value.vfloat /= pSrcSyn->value.vfloat;
            break;
        case ADD_ASSIGN:
            pSym->value.vfloat += pSrcSyn->value.vfloat;
            break;
        case SUB_ASSIGN:
            pSym->value.vfloat -= pSrcSyn->value.vfloat;
            break;
        }
        break;

    case EXPR_INT << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int;
        pSym->value.vint = std::floor(pSrcSyn->value.vfloat);

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint = std::floor(pSrcSyn->value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint *= std::floor(pSrcSyn->value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint /= std::floor(pSrcSyn->value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint += std::floor(pSrcSyn->value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint -= std::floor(pSrcSyn->value.vfloat);
            break;
        }
        if (iswarn)
        {
            //std::cout << u8"小数赋值给整数类型，可能丢失精度"  << std::endl;
        }
        break;
    case EXPR_INT64 << 16 | EXPR_FLOAT:
        ret = EXPR_Float_to_Int64;

        switch(op)
        {
        case EQUAL_ASSIGN:
            pSym->value.vint64 = std::floor(pSrcSyn->value.vfloat);
            break;
        case MUL_ASSIGN:
            pSym->value.vint64 *= std::floor(pSrcSyn->value.vfloat);
            break;
        case DIV_ASSIGN:
            pSym->value.vint64 /= std::floor(pSrcSyn->value.vfloat);
            break;
        case ADD_ASSIGN:
            pSym->value.vint64 += std::floor(pSrcSyn->value.vfloat);
            break;
        case SUB_ASSIGN:
            pSym->value.vint64 -= std::floor(pSrcSyn->value.vfloat);
            break;
        }
        if (iswarn)
        {
            std::cout << u8"小数赋值给长整数类型，可能丢失精度" << std::endl;
        }
        break;
    case EXPR_STRING << 16 | EXPR_STRING:
    {
        ret = EXPR_String_to_String;

            switch(op)
            {
            case EQUAL_ASSIGN:
            {
                //注意这里是深拷贝，这是和其它可能不一样的地方。
                if (pSym->value.vpoint != nullptr)
                {
                    delete (QByteArray*)pSym->value.vpoint;
                    pSym->value.vpoint = nullptr;
        #ifdef PIN_MEM_REF
            freeTimes++;
        #endif
                }
                if(pSrcSyn->value.vpoint != nullptr)
                {
                    pSym->value.vpoint = new QByteArray(*(QByteArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
    newTime();
#endif
                }
            }
                break;
            case MUL_ASSIGN:
            case SUB_ASSIGN:
            case DIV_ASSIGN:
                break;
            case ADD_ASSIGN:
            {
                if (pSrcSyn->value.vpoint != nullptr)
                {
                    if (pSym->value.vpoint != nullptr)
                    {
                        ((QByteArray*)pSym->value.vpoint)->append(*(QByteArray*)pSrcSyn->value.vpoint);
                    }
                    else
                    {
                        pSym->value.vpoint = new QByteArray(*(QByteArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
                        newTime();
#endif
                    }
                }
            }
                break;
            }

    }
        //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
        break;

    case EXPR_U16STRING << 16 | EXPR_U16STRING:
    {
        ret = EXPR_U16String_to_U16String;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            //注意这里是深拷贝，这是和其它可能不一样的地方。
            if (pSym->value.vpoint != nullptr)
            {
                delete (QString*)pSym->value.vpoint;
                pSym->value.vpoint = nullptr;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            }
            if (pSrcSyn->value.vpoint != nullptr)
            {
                pSym->value.vpoint = new QString(*(QString*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
        }
        break;
        case MUL_ASSIGN:
        case SUB_ASSIGN:
        case DIV_ASSIGN:
            break;
        case ADD_ASSIGN:
        {
            if (pSrcSyn->value.vpoint != nullptr)
            {
                if (pSym->value.vpoint != nullptr)
                {
                    ((QString*)pSym->value.vpoint)->append(*(QString*)pSrcSyn->value.vpoint);
                }
                else
                {
                    pSym->value.vpoint = new QString(*(QString*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
                    newTime();
#endif
                }
            }
        }
        break;
        }

    }
    //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
    break;

    case EXPR_U16STRING << 16 | EXPR_STRING:
    {
        ret = EXPR_String_to_U16String;

        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            if (pSym->value.vpoint == nullptr)
            {
                pSym->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            else
            {
                //注意这里是深拷贝，这是和其它可能不一样的地方。
                ((QString*)(pSym->value.vpoint))->clear();
            }

            if (pSrcSyn->value.vpoint != nullptr)
            {
                ((QString*)(pSym->value.vpoint))->append((*(QByteArray*)pSrcSyn->value.vpoint));
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
        }
        break;
        case MUL_ASSIGN:
        case SUB_ASSIGN:
        case DIV_ASSIGN:
            break;
        case ADD_ASSIGN:
        {
            if (pSrcSyn->value.vpoint != nullptr)
            {
                if (pSym->value.vpoint != nullptr)
                {
                    ((QString*)pSym->value.vpoint)->append(*(QByteArray*)pSrcSyn->value.vpoint);
                }
                else
                {
                    pSym->value.vpoint = new QString(*(QByteArray*)pSrcSyn->value.vpoint);
#ifdef PIN_MEM_REF
                    newTime();
#endif
                }
            }
        }
        break;
        }

    }
    //后续如果发现这里会一个表达式，多次赋值给其它，则需要修改为深拷贝。别忘记了。
    break;

    case EXPR_BOOL <<16 | EXPR_BOOL:
        ret = EXPR_Bool_to_Bool;
        pSym->value.vbool = pSrcSyn->value.vbool;
        break;

        //结构体一定是深拷贝
    case EXPR_STRUCT <<16 | EXPR_STRUCT:
    {
        switch(op)
        {
        case EQUAL_ASSIGN:
            {

            pSym->freeMem();//必须释放之前的。

            ret = EXPR_Struct_to_Struct;
            //深拷贝一下
            STRUCT_VALUE_DATA* pSv = (STRUCT_VALUE_DATA*)pSrcSyn->value.vpoint;
            pSym->value.vpoint = pSv->deepCopy();
            }
            break;
        }
    }
        break;

    case EXPR_STRUCT_DEC << 16 | EXPR_STRUCT_DEC:
    {
        switch (op)
        {
        case EQUAL_ASSIGN:
        {

            pSym->freeMem();//必须释放之前的。

            ret = EXPR_StructDesc_to_StructDesc;

            //结构体类型申明
            // 
            //深拷贝一下
            std::vector<std::string>* pSv = (std::vector<std::string>*)pSrcSyn->value.vpoint;
            pSym->value.vpoint = new std::vector<std::string>(*pSv);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        break;
        }
    }
    break;

    case EXPR_LIST <<16 | EXPR_LIST:
        switch(op)
        {
            case EQUAL_ASSIGN:
            {
                pSym->freeList();
                ret = EXPR_List_to_List;
                pSym->value.vpoint = pSrcSyn->value.vpoint;
                addListMapRefNum(pSym->value.vpoint);
            }
            break;
        }
        break;

    case EXPR_MAP <<16 | EXPR_MAP:
        switch(op)
        {
            case EQUAL_ASSIGN:
            {
                pSym->freeMap();
                ret = EXPR_Map_to_Map;
                pSym->value.vpoint = pSrcSyn->value.vpoint;
                addListMapRefNum(pSym->value.vpoint);
            }
            break;
        }
        break;
    case EXPR_FILE << 16 | EXPR_FILE:
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            pSym->freeFile();
            ret = EXPR_File_to_File;
            pSym->value.vpoint = pSrcSyn->value.vpoint;
            addListMapRefNum(pSym->value.vpoint);
        }
        break;
        }
        break;
    case EXPR_EXCEL << 16 | EXPR_EXCEL:
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            pSym->freeExcel();
            ret = EXPR_Excel_to_Excel;
            pSym->value.vpoint = pSrcSyn->value.vpoint;
            addListMapRefNum(pSym->value.vpoint);
        }
        break;
        }
        break;
    case EXPR_DATE << 16 | EXPR_DATE:
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_Date_to_Date;
            pSym->freeMem();
            if(pSrcSyn->value.vpoint != nullptr)
            {
            pSym->value.vpoint = new QDateTime(*(QDateTime*)(pSrcSyn->value.vpoint));
#ifdef PIN_MEM_REF
            newTime();
#endif
            }
            else
            {
                pSym->value.vpoint = nullptr;
            }
        }
        break;
        }
        break;

    case EXPR_CHAR << 16 | EXPR_CHAR:
    {
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_Char_to_Char;
            pSym->value.vchar = pSrcSyn->value.vchar;
        }
        break;
        }
    }
        break;

    case EXPR_WCHAR << 16 | EXPR_WCHAR:
    {
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_WChar_to_WChar;
            pSym->value.vwchar = pSrcSyn->value.vwchar;
        }
        break;
        }
    }
    break;

    case EXPR_WCHAR << 16 | EXPR_CHAR:
    {
        switch (op)
        {
        case EQUAL_ASSIGN:
        {
            ret = EXPR_Char_to_WChar;
            pSym->value.vwchar = pSrcSyn->value.vchar;
        }
        break;
        }
    }
    break;

    default:
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 无法使用 %3 类型给表达式赋值，类型不匹配或表达式错误 !").arg(curLine).arg(curStatement).arg(QStr(pSrcSyn->name));
        AbortException(msg);
        //std::cout << msg.toStdString() << std::endl; //在外面报错信息更全
    }
        break;
    }
    if (iswarn && ret < 0)
    {
        //std::cout << u8"变量的类型和其赋值无法匹配！请检查。" << std::endl;
        QString msg = QString(u8"错误：行号 %1 语句 %2 无法使用 %3 类型给表达式赋值，类型不匹配或表达式错误 !").arg(curLine).arg(curStatement).arg(QStr(pSrcSyn->name));
        AbortException(msg);

    }

    return ret;
}


//这里的string是使用QByteArray来存放的。一定要注意这个内存的释放。
//在放入到符号表时，最终这个是由符号表存放。如果不放，则要及时释放掉。
std::any ExprVisitor::visitStrExpr(PinParser::StrExprContext* ctx)
{
	//std::cout << ctx->getText();

	std::string str = ctx->getText();

	//转换为qt的字符串
	//QString qStr = QString::fromStdString(str);

	QByteArray qbytes = QByteArray::fromStdString(str);

    bool isU16 = false;

    //是不是u16
    if (qbytes.startsWith("u16"))
    {
        isU16 = true;

        const char* data = qbytes.data();
        int i = 3, s = qbytes.size();
        for (; i < s; ++i)
        {
            if (data[i] == '\'' || data[i] == '"')
            {
                break;
            }
        }
        qbytes = qbytes.mid(i);
    }

	QByteArray escBytes = lexBytesToEscapeBytes(qbytes);

    ExprValue ret;


    if (!isU16)
    {
    ret.type = EXPR_STRING;
    ret.value.vpoint = new QByteArray(escBytes);
    }
    else
    {
        ret.type = EXPR_U16STRING;
        ret.value.vpoint = new QString(escBytes);
    }

    #ifdef PIN_MEM_REF
    newTime();
    #endif

    return ret;
}

std::any ExprVisitor::visitRowStrExpr(PinParser::RowStrExprContext *ctx)
{
    std::string str = ctx->getText();

    //转换为qt的字符串
    //QString qStr = QString::fromStdString(str);

    QByteArray qbytes = QByteArray::fromStdString(str);

    QByteArray escBytes = lexRawBytesToEscapeBytes(qbytes);

    //std::cout << escBytes.toStdString();

    //return ctx->getText();
    ExprValue ret;
    ret.type = EXPR_STRING;
    ret.value.vpoint = new QByteArray(escBytes);

#ifdef PIN_MEM_REF
    newTime();
#endif

    return ret;
}

//进入定义模式
std::any ExprVisitor::visitDefvar(PinParser::DefvarContext *ctx)
{
	#ifdef PIN_DEBUG
     //进入定义模式
    std::cout << u8"进入定义语句" << ctx->getText() << std::endl;
#endif

    pin_status_info pinInfo;

    //获取定义变量类型
    std::string varType = ctx->TYPE_ID()->getText();


    int type = getVarTypeByName(varType);

    pinInfo.data = type;

    switch (type)
    {
        case EXPR_INT:
        case EXPR_INT64:
        case EXPR_FLOAT:
        case EXPR_STRING:
        case EXPR_CHAR:
        case EXPR_WCHAR:
        case EXPR_U16STRING:
        case EXPR_BOOL:
        case EXPR_LIST:
        case EXPR_MAP:
        case EXPR_FILE:
        case EXPR_DATE:
        case EXPR_EXCEL:
            break;//合法

        case EXPR_STRUCT:
        case EXPR_FUN:
        {
            //非法
            QString msg = QString(u8"错误：行号%1 语句 %2 非法的定义类型 %3").arg(curLine).arg(curStatement).arg(QStr(varType));
            AbortException(msg);
        }
        break;
        default:
            break;
    }

    //如果当前在全局，则进入全局定义
    if (getPinRunStatus() == INTO_GLOBAL)
    {
        pinInfo.status = GLOBAL_DEFVAR_STATUS;
        pushStatus(pinInfo);
    }
    else
    {
        pinInfo.status = DEFVAR_STATUS;
        pushStatus(pinInfo);
    }

    //是定义加赋值
    if(ctx->assign() != nullptr)
    {
        visit(ctx->assign());
    }
    else if(ctx->VARNAME(0) != nullptr)
    {
        std::vector<tree::TerminalNode*> pVarVec = ctx->VARNAME();


        for (int i = 0, s = pVarVec.size(); i < s; ++i)
        {

            //检查变量是否存在
            std::string varName = pVarVec.at(i)->getText();

            //不能是关键字
            if (isKeyWordTypeVar(varName))
            {
                QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 名称使用了pin内部保留关键字，还请改名！").arg(globalCurLine).arg(curStatement).
                    arg(QStr(varName));
                AbortException(errmsg);
            }

            if (pinInfo.status == GLOBAL_DEFVAR_STATUS)
            {
                if (isGloablVarAlreadyExist(varName))
                {
                //变量已经存在，不能重复定义
                QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 在全局作用域已经存在，不能重复定义！").arg(globalCurLine).arg(curSrcStatement).
                    arg(QStr(varName));
                AbortException(errmsg);
            }
            }
            else
            {
                //检查当前作用域是不是已经存在该变量，如果是则要报错。
                if (isLoaclVarAlreadyExist(varName))
                {
                    //变量已经存在，不能重复定义
                    QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 在当前作用域已经存在，不能重复定义 !").arg(curLine).arg(curSrcStatement).arg(QStr(varName));
                    AbortException(msg);
                }
            }

            SymNode* pNewVar = new SymNode();
            pNewVar->type = type;
            pNewVar->name = varName;
#ifdef PIN_MEM_REF
            newTime();
#endif
            //使用类型的初始化赋值。
            switch (type)
            {
            case EXPR_INT:
            {
                pNewVar->value.vint = 0;
            }
            break;

            case EXPR_INT64:
            {
                pNewVar->value.vint64 = 0;
            }
            break;

            case EXPR_FLOAT:
            {
                pNewVar->value.vfloat = 0.1f;
            }
            break;

            case EXPR_STRING:
            {
                pNewVar->value.vpoint = new QByteArray();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            break;

            case EXPR_U16STRING:
            {
                pNewVar->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            break;

            case EXPR_CHAR:
            {
                pNewVar->value.vchar = 'a';
            }
            break;

            case EXPR_WCHAR:
            {
                pNewVar->value.vwchar = 'a';
            }
            break;

            case EXPR_BOOL:
            {
                pNewVar->value.vbool = false;
            }
            break;

            case EXPR_LIST:
            {
                pNewVar->value.vpoint = new std::vector<ExprValue_*>();
                addListMapRefNum(pNewVar->value.vpoint);
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            break;

            case EXPR_MAP:
            {
                pNewVar->value.vpoint = new std::unordered_map<ExprValue, ExprValue*>();
                addListMapRefNum(pNewVar->value.vpoint);
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            break;

            //这两个文件，都是可以为空的。
            case EXPR_FILE:
            {
                pNewVar->value.vpoint = nullptr;
            }
            break;

            //日期也不能是空了，默认要给一个。20250321修改了。见SetData isNull 这些方法，没法绕过。
            case EXPR_DATE:
            {
                pNewVar->value.vpoint = new QDateTime();
#ifdef PIN_MEM_REF
                newTime();
#endif
            }
            break;


            case EXPR_EXCEL:
            {
                EXCEL_VALUE_DATA* pExcelFileData = new EXCEL_VALUE_DATA();
                pExcelFileData->pDoc = new OpenXLSX::XLDocument;
#ifdef PIN_MEM_REF
                newTime(2);
#endif
                pNewVar->value.vpoint = pExcelFileData;
                addListMapRefNum(pExcelFileData);
            }
            break;//合法
            }

            //加入栈
            if (pinInfo.status == GLOBAL_DEFVAR_STATUS)
            {
                insertGlobalSymTable(varName, pNewVar);
            }
            else
            {
                getPinSymTable()->append(pNewVar);
            }
        }
    }

    popStatus();
#ifdef PIN_DEBUG
    std::cout << u8"退出定义语句" << ctx->getText() << std::endl << std::endl;
	#endif
    return 0;
}


//定义结构体变量
std::any ExprVisitor::visitDefstvar(PinParser::DefstvarContext *ctx)
{
    std::vector<tree::TerminalNode *> stDecVec = ctx->VARNAME();

    std::string stName;

    if(stDecVec.size() >= 1)
    {
        stName = stDecVec.at(0)->getText();
    }

    //如果有多个，则都必须一样
    for(int i=1; i < stDecVec.size(); ++i)
    {
        if(stName != stDecVec.at(i)->getText())
        {
            QString msg = QString(u8"错误：行号 %1 语句 %2 结构类型 %3 与 前面类型 %4 不一样， 一次性定义多个结构体时，必须都是同一个类型的结构体！").arg(curLine)
                    .arg(curStatement).arg(QStr(stDecVec.at(i)->getText())).arg(QStr(stName));
            AbortException(msg);

            return 0;
        }
    }

    //检查结构体声明的类型是否存在。
    SymNode* pStSym = getVarFromGlobalSymTable(stName,ctx,1);

    if(pStSym != nullptr)
    {
        std::vector<PinParser::OnestContext *> oneVec = ctx->onest();

        for(int i=0,c = oneVec.size(); i<c; ++i)
        {
            antlr4::tree::TerminalNode * pNode = nullptr;

            bool isNeedInit = false;

            //只定义不赋值。
            if(oneVec.at(i)->VARNAME())
            {
                //定义结构体变量。需要直接初始化，否则可能字符串为空崩溃。
                pNode = oneVec.at(i)->VARNAME();
                isNeedInit = true;
            }
            else if(oneVec.at(i)->assignStOne())
            {
                pNode = oneVec.at(i)->assignStOne()->VARNAME();
                //已有逻辑，不需要再写。但是先要定义
                //visit(oneVec.at(i)->assignStOne());
            }

            //检查变量是否已经存在
            std::string varName = pNode->getText();

            if (getPinRunStatus() != INTO_GLOBAL)
            {
                //变量是否已经存在
                //检查当前作用域是不是已经存在该变量，如果是则要报错。
                if (isLoaclVarAlreadyExist(varName))
                {
                    //变量已经存在，不能重复定义
                    QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 在当前作用域已经存在，不能重复定义 !").arg(curLine).arg(curSrcStatement).arg(QStr(varName));
                    AbortException(msg);
                    return 0;
                }
            }
            else
            {
                //检查全局作用域是不是已经存在该变量，如果是则要报错。
               if (isGloablVarAlreadyExist(varName))
               {
                   //变量已经存在，不能重复定义
                   QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 在全局作用域已经存在，不能重复定义！").arg(globalCurLine).arg(curSrcStatement).
                                    arg(QStr(varName));
                   AbortException(errmsg);
                   return 0;
               }
            }

                //依次定义结构变量

                    SymNode* oneSt = new SymNode();
					#ifdef PIN_MEM_REF
            newTime();
#endif
                    oneSt->name = pNode->getText();

                    oneSt->type = EXPR_STRUCT;

                    STRUCT_VALUE_DATA* sv = new STRUCT_VALUE_DATA();
					#ifdef PIN_MEM_REF
            newTime();
#endif
                    sv->structType = stName;
                    sv->structTypeId = getStructIdByDescName(stName);
                    oneSt->value.vpoint = sv;

                    //把值初始化一下
                    std::vector<std::string>* paraList = (std::vector<std::string>*)pStSym->value.vpoint;

                    int paraNum = paraList->size()/2;

                    if (paraNum > 0)
                    {
                        std::vector<ExprValue*>* valueList = new std::vector<ExprValue*>(paraNum);
#ifdef PIN_MEM_REF
                        newTime();
#endif
                        //前面一半是变量，后面一半是类型
                        for (int j = 0, c = paraNum; j < c; ++j)
                        {
                            ExprValue* pv = new ExprValue();
#ifdef PIN_MEM_REF
                            newTime();
#endif
                            pv->type = getVarTypeByName(paraList->at(j + paraNum));

                            //后面马上要赋值，则这里可以先不给初始值，避免做无用功。
                            if (!isNeedInit)
                            {
                                pv->value.vint64 = 0; //按最大的来，统一给0
                            }
                            else
                            {
                                //这里必须初始化，因为只定义，不赋值，后续直接使用时，字符串会崩溃。
                                switch (pv->type)
                                {
                                case EXPR_STRING:
                                    pv->setString("");
                                    break;
                                case EXPR_U16STRING:
                                {
                                    pv->value.vpoint = new QString();
#ifdef PIN_MEM_REF
                                    newTime();
#endif
                                }
                                    break;
                                default:
                                    pv->value.vint64 = 0;
                                    break;
                                }
                            }
                            (*valueList)[j] = pv;

                        }

                        sv->pValue = valueList;
                    }

                    switch (sv->structTypeId)
                    {
                    //    case PString_Struct_Id:
                    //        //初始化为空字符QString对象
                    //    {
                    //        sv->pCppObj = QString();
                    //    }
                    //        break;
                          case REGEXP_Struct_ID:
                          {
                                //初始化为 QRegularExpression
                                sv->pCppObj = QRegularExpression();
                          }
                          break;

                        case REGMATCH_Struct_ID:
                        {
                              //初始化为 QRegularExpression
                              sv->pCppObj = QRegularExpressionMatch();
                        }
                        break;

                        case REGMATCH_ITER_Struct_ID:
                        {
                            //初始化为 QRegularExpression
                            sv->pCppObj = QRegularExpressionMatchIterator();
                    }
                        break;
                    }


                    if (getPinRunStatus() == INTO_GLOBAL)
                    {
                       insertGlobalSymTable(oneSt->name,oneSt);
                    }
                    else
                    {
                        //加入到符号表中
                        getPinSymTable()->append(oneSt);
                    }


                    if(oneVec.at(i)->assignStOne())
                    {
                          //已有逻辑，不需要再写。但是先要定义
                        visit(oneVec.at(i)->assignStOne());
                    }

        }

    }
    return 0;
}


//全局访问。
std::any ExprVisitor::visitDefglobal(PinParser::DefglobalContext *ctx)
{
    return visitChildren(ctx);
}

/*
//全局块
std::any ExprVisitor::visitGlobalblock(PinParser::GlobalblockContext *ctx)
{
    visitChildren(ctx);
    return 0;
}
*/


std::any ExprVisitor::visitForinc(PinParser::ForincContext* ctx)
{
    if(ctx->assginNoEnd() != nullptr)
    {
        visit(ctx->assginNoEnd());
    }
    else if(ctx->pinAutoAddSub() != nullptr)
    {
        visit(ctx->pinAutoAddSub());
    }
    std::vector<PinParser::ForincContext*> exprVec =  ctx->forinc();

    for (int i = 0, s = exprVec.size(); i < s; ++i)
    {
        visit(exprVec.at(i));
    }

    return 0;
}


/*
EQUAL_ASSIGN=0,
    MUL_ASSIGN,
    DIV_ASSIGN,
    ADD_ASSIGN,
    SUB_ASSIGN,*/
AssignOpType getOptype(std::string & op)
{
    const char* code = op.data();

    switch (code[0])
    {
    case('='):
        return EQUAL_ASSIGN;
    //case (':'):
    //    reurn DEFINE_ASSIGN;
    case ('+'):
            return ADD_ASSIGN;
    case ('/'):
        return DIV_ASSIGN;
    case ('*'):
        return MUL_ASSIGN;
    case ('-' ):
        return SUB_ASSIGN;

    default:
        break;
    }
    return EQUAL_ASSIGN;
}


//声明结构体
std::any ExprVisitor::visitDeclareStruct(PinParser::DeclareStructContext *ctx)
{
    //如果是在全局区，则加入全局符号表
    if(getPinRunStatus() == INTO_GLOBAL)
    {
        //如果是在全局区域，则把结构体申请放入全局
        std::string stName = ctx->VARNAME()->getText();

        //先看看有没有，有则不加入，说明重复
        if(isGlobalSymExist(stName))
        {
            QString msg = QString(u8"错误：语句 %1 全局区域变量 %2 重复定义 ！").arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(stName));
            AbortException(msg);
            return 0;
        }

        std::vector<PinParser::Struct_varContext *> stMember = ctx->struct_body()->struct_var();

        SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif
        newVar->name = stName;
        newVar->type = EXPR_STRUCT_DEC; //结构体声明类型，这里是以符号表加入到全局中的。

        //前面是变量，后面是类型
        std::vector<std::string>* pParalist = new std::vector<std::string>(stMember.size()*2);
#ifdef PIN_MEM_REF
        newTime();
#endif
        //先加入成员变量的名称
        for(int i=0, s = stMember.size(); i<s; ++i)
        {
            (*pParalist)[i] = stMember.at(i)->VARNAME()->getText();
        }

        //再加入变量的类型
        for(int i=0, s = stMember.size(); i<s; ++i)
        {
            (*pParalist)[i+s] = stMember.at(i)->TYPE_ID()->getText();
        }

        newVar->value.vpoint = pParalist;

        insertGlobalSymTable(stName,newVar);
    }
    else
    {
        //只能在全局区域声明结构体
        QString msg = QString(u8"错误：语句 %1 结构体的声明，只能在全局区域中！").arg(QString::fromStdString(ctx->getText()));
        AbortException(msg);
    }
    return 0;
}

//目前只用在函数的返回值中。函数返回值返回结构体中的成员变量。
int ExprVisitor::assignStructMem(SymNode* pSym, PinParser::StMemVarContext* pStructMem, SymNode* pSrvVar, antlr4::ParserRuleContext* ctx)
{
    if(pSym->type == EXPR_STRUCT)
    {
        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
        int index = getMemIndexFromStruct(pValue->structType, pStructMem->getText(), ctx);
        if(index != -1)
        {
            //ExprValue ret;
            //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
            //ExprValue exprRet = std::any_cast<ExprValue>(visit(pExpr));

            ExprValue* exprSrc = (*(std::vector<ExprValue*>*)pValue->pValue)[index];

            //std::string op = ctx->assignOp()->getText();
            //AssignOpType optype = getOptype(op);

            //FillExprByExpr(&exprSrc,&exprRet,true,optype);

            FillExprBySymNode(exprSrc,pSrvVar,ctx,true);


            //这里其实不需要，因为FillExprByExpr里面会调用释放，进行内存的转移。
            //exprRet.freeMem();

            return 0;

        }
        else
        {
            QString msg= QString(u8"错误：行号 %1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pStructMem->getText()));
            AbortException(msg);
        }

    }
    else
    {
        QString msg= QString(u8"错误：行号 %1 语句 %2 变量 %3 非法的结构体，可能不是结构体!").arg(curLine).arg(curStatement).arg(QStr(pSym->name));
        AbortException(msg);
    }
    return 0;
}

#if 0
//目前只用在函数的返回值中。函数返回值返回列表中的成员变量。
int ExprVisitor::assignList(PinParser::AccesslistContext* pList, SymNode* pSrvVar, antlr4::ParserRuleContext *ctx)
{
   // PinParser::AccesslistContext* pList = ctx->pinvar()->accesslist();
    std::string listName = pList->LIST_ID()->getText();
    SymNode* pSym = getVarFromSymTable(listName, ctx);

    PinParser::StMemVarContext* pMem = pList->stMemVar();

    //直接列表赋值给列表,只有结构体才能有.mem，[x].mem 必须要有[]
    if(pList->listindex().size() == 0)
    {
        //不能有.mem，理由如上。
        if(pMem != nullptr)
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 列表 %3 不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(QStr(pMem->getText()));
            AbortException(msg);
            return 0;
        }

        //左值是列表，则右值也只能是列表。列表赋值给列表。
        //列表赋值给列表，右值列表以表达式方式进行赋值。

        //必须是列表才行
        if(pSrvVar->type == EXPR_LIST && pSym->type == EXPR_LIST)
        {
            //因为是赋值，先把左边的释放,这里是计数判断释放，不一定真正释放。只有里面为0时，才会真正释放内存。
            pSym->destory();

            //和python保持一致：所有列表 map的赋值，默认都是浅拷贝。
            pSym->value.vpoint = pSrvVar->value.vpoint;
            addListMapRefNum(pSym->value.vpoint);

            return 0;

        }
        else
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 不能把非列表类型语句 %3 赋值给列表 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pSrvVar->name)).arg(QStr(listName));
            AbortException(msg);
        }
    }
    else
    {
        //访问列表下面的元素
        std::vector<PinParser::ListindexContext *> indexVec = pList->listindex();

        //最开始是第一层列表，依次深入
        std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;

        for(int i=0,c=indexVec.size(); i<c; ++i)
        {
            ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
            //必须是整数类型.INT64不行。
            if(ev.type == EXPR_INT)
            {
                //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                int index = ev.value.vint;

                if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                {
                    ExprValue* ev = pchildlist->at(index);
                    if(ev->type == EXPR_LIST && i <(c-1))
                    {
                        //这里就是开始解开列表，往里面一层一层的剥列表
                        pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                        continue;
                    }
                    else if(i  == (c-1))
                    {
                        if(pMem == nullptr)
                        {
                            //解到最后一层列表结果
                            //因为是赋值，先把左边的释放。这个pExpr还是可能是列表
                            //ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                            //不能是map，map目前不能赋值给列表
                            if(pSrvVar->type == EXPR_MAP)
                            {
                                QString msg = QString(u8"错误：函数 %1 语句 %2 不能把字典类型 %3 赋值给列表 %4 或其元素值!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pSrvVar->name)).arg(QStr(listName));
                                AbortException(msg);
                                return 0;
                            }

                            //因为是赋值，先把左边的值释放。列表或字典，是共享内存，其余都是独立内存
                            //里面需要走引用计数逻辑。
                            ev->freeMem();

                            //这里一定要注意，因为这里的类型其实是可能变换的，比如从int变成列表或结构
                            //只能使用FillExprBySymNode
                            ev->type = pSrvVar->type;

                            FillExprBySymNode(ev, pSrvVar,ctx,true);

                            //不需要，如果是列表或字典，FillExprBySymNode已经做过了
                            //addListMapRefNum(*ev);

                        }
                        else
                        {
                            //继续按照结构体方式来解析
                            if(ev->type == EXPR_STRUCT)
                            {
                                STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                if(index != -1)
                                {
                                    //ExprValue ret;
                                    //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                    std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                    ExprValue* ret = (*pVec)[index];

                                    //ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                    //这里只能是基本元素类型。
                                    FillExprBySymNode(ret, pSrvVar,ctx,true);

                                }
                                else
                                {
                                    QString msg= QString(u8"错误：函数%1 语句 %2 列表第 %3 个元素的结构体类型 %4 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                    AbortException(msg);
                                }
                            }
                        }

                        return 0;

                    }
                    else
                    {
                        QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                        AbortException(msg);
                    }
                }
                else
                {
                    QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                    AbortException(msg);
                }
            }
            else
            {
                QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                AbortException(msg);
            }
        }

        return 0;
    }

    return 0;
}

//目前只用在函数的返回值中。函数返回值返回字典中的成员变量。
int ExprVisitor::assignMap(PinParser::AccessmapContext* pMap, SymNode* pSrvVar, antlr4::ParserRuleContext *ctx)
{
    //PinParser::AccessmapContext* pMap = ctx->pinvar()->accessmap();
    std::string mapName = pMap->MAP_ID()->getText();
    SymNode* pSym = getVarFromSymTable(mapName, ctx);


    PinParser::StMemVarContext* pMem = pMap->stMemVar();
    std::vector<PinParser::ListindexContext *> indexVec = pMap->listindex();

    //最开始是第一层列表，依次深入
    std::unordered_map<ExprValue, ExprValue*>* pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)pSym->value.vpoint;
    std::vector<ExprValue*>* pchildlist = nullptr;

    if(indexVec.size() == 0)
    {
        if(pMem != nullptr)
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 字典 %3 不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(pMem->getText()));
            AbortException(msg);

        }

        //必须是字典才行
        if(pSrvVar->type == EXPR_MAP && pSym->type == EXPR_MAP)
        {
            //因为是赋值，先把左边的释放
            pSym->destory();

            //已经明确是字典，转移浅拷贝即可。
            pSym->value.vpoint = pSrvVar->value.vpoint;
            addListMapRefNum(pSym->value.vpoint);

            return 0;
        }
        else
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 不能把非字典类型语句 %3 赋值给字典 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pSym->name)).arg(QStr(mapName));
            AbortException(msg);
        }
    }

    //以下必然是zd_1[x]访问的方式

    int i = 0;
    std::string curkey;
    ExprValue* pListElem;

           for(int c=indexVec.size(); i<c; ++i)
           {
               const ExprValue key = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
               //必须是整数类型.INT INT64 或 字符串
               if(key.type == EXPR_INT || key.type == EXPR_INT64 || key.type == EXPR_STRING)
               {

                   if(pchildmap != nullptr)
                   {
                       ExprValue* ev = nullptr;

                       auto it = pchildmap->find(key);

                       //找到
                       if(it != pchildmap->end())
                       {
                           ev = it->second;

                           //还需要继续往下剥,而且还能继续剥
                           if(ev->type == EXPR_MAP && (i< (c-1)))
                           {
                               //这里就是开始解开列表，往里面一层一层的剥列表
                               pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)ev->value.vpoint;
                               continue;
                           }
                           else if(ev->type == EXPR_LIST)
                           {
                               //特殊情况，遇到列表了
                               //这里就是开始解开列表，往里面一层一层的剥列表
                               //跳出map，开始解列表
                               curkey = indexVec.at(i)->expr()->getText();
                               pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                               pListElem = ev;
                               break;
                           }
                           else if(i == (c-1)) //不需要继续往下剥
                           {
                               if(pMem == nullptr)
                               {
                                   //解到最后一层列表结果
                                   //因为是赋值，先把左边的释放。这个rightvar可能是list或map
                                   //ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                   //因为是赋值，先把左边的值释放
                                   ev->freeMem();


                                   ev->type = pSrvVar->type;

                                   //这里千万不能这样，因为可能是字符串、结构体，或者列表。如果是字符串或结构体，则会浅拷贝导致崩溃
                                   //ev->value.vint64 = pSrvVar->value.vint64;

                                   //addListMapRefNum(*ev);
                                   FillExprBySymNode(ev, pSrvVar,ctx,true);
                               }
                               else
                               {
                                   //继续访问结构体
                                   if(ev->type == EXPR_STRUCT)
                                   {
                                       STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                       int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                       if(index != -1)
                                       {
                                           //ExprValue ret;
                                           //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                           std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                           ExprValue* ret = (*pVec)[index];


                                            //ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                            //这里只能是基本元素类型。
                                            FillExprBySymNode(ret,pSrvVar,ctx,true);
                                       }
                                       else
                                       {
                                           QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                           AbortException(msg);
                                       }
                                   }
                                   else
                                   {
                                       QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                       AbortException(msg);
                                   }
                               }
                                return 0;
                           }
                       }//没有找到map的key
                       else
                       {
                            //没有发现元素，新加入一个元素
                           //使用[key] = value 方式加入
                           //如果是最后一层，则直接加入一个键值。
                           if(i == (c-1))
                           {
                               //ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));



                               ExprValue rightExpr;
                               rightExpr.type = pSrvVar->type;
                               //rightExpr.value.vpoint = pSrvVar->value.vpoint;
                               FillExprBySymNode(&rightExpr,pSrvVar,ctx,true);

                               pchildmap->insert({key,rightExpr.shallowMoveCopy()});

                               return 0;
                           }
                           else
                           {
                               QString msg = QString(u8"错误：函数 %1 语句 %2 字典关键字key %3 对应值不存在，无法继续加入子项目！").arg(getCurFunQSName()).arg(curStatement).arg(QStr(indexVec.at(i)->expr()->getText()));
                               AbortException(msg);
                           }

                       }
                   }
               }
               else
               {
                   QString msg = QString(u8"错误：函数 %1 语句 %2 字典%3 访问元素第 %4 个关键字 %5 类型错误，字典关键字索引只能是整数或字符串类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(i).arg(QStr(indexVec.at(i)->expr()->getText()));
                   AbortException(msg);
               }
           }

           //遇到列表访问
           if(pchildlist != nullptr)
           {
               ++i;//继续解访问后面的列表

               //直接访问列表，后面没有更多[]号了
               if(i == indexVec.size())
               {
                   if(pMem != nullptr)
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 字典 %3 不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(pMem->getText()));
                       AbortException(msg);

                   }
                   //列表获取都是浅拷贝而来。
                   //ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                   //必须是列表才行。这里不对，是可以修改类型的，不需要是列表。比如可以修改原来的列表为结构体。
                   //if(rightExpr.type == EXPR_LIST && pListElem->type == EXPR_LIST)
                   {

                       pListElem->freeMem();


                       pListElem->type = pSrvVar->type;
                       //pListElem->value.vint64 = pSrvVar->value.vint64;
                       //addListMapRefNum(*pListElem);

                       FillExprBySymNode(pListElem,pSrvVar,ctx,true);


                       return 0;

                   }
                   /*else
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 不能把非列表类型语句 %3 赋值给字典关键字 %4 对应的值 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(curkey));
                       AbortException(msg);
                   }*/
               }

              int listStart = i;
               //最开始是第一层列表，依次深入
              for(int c=indexVec.size(); i<c; ++i)
               {
                   ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                   //必须是整数类型.INT64不行。
                   if(ev.type == EXPR_INT)
                   {
                       //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                       int index = ev.value.vint;

                       if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                       {
                           ExprValue* ev = pchildlist->at(index);

                           //还需要继续往下剥,而且还能继续剥
                           if(ev->type == EXPR_LIST && (i< (c-1)))
                           {
                               //这里就是开始解开列表，往里面一层一层的剥列表
                               pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                               continue;
                           }
                          /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                           {
                               //这里就是开始解开列表，往里面一层一层的剥列表
                               QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                               AbortException(msg);
                           }*/
                           else if(i == (c-1)) //不需要继续往下剥
                           {
                               if(pMem == nullptr)
                               {
                                   //解到最后一层列表结果
                                   //因为是赋值，先把左边的释放,字典没有限制
                                   //ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                   //因为是赋值，先把左边的值释放
                                   ev->freeMem();

                                   ev->type = pSrvVar->type;
                                   //ev->value.vint64 = pSrvVar->value.vint64;
                                   //addListMapRefNum(*ev);
                                   FillExprBySymNode(ev,pSrvVar,ctx,true);


                               }
                               else
                               {
                                   //继续访问结构体
                                   if(ev->type == EXPR_STRUCT)
                                   {
                                       STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                       int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                       if(index != -1)
                                       {
                                           //ExprValue ret;
                                           //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                           std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                           ExprValue* ret = (*pVec)[index];


                                           //ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                           //这里只能是基本元素类型。如果是字符串，里面会做浅拷贝move操作
                                           FillExprBySymNode(ret,pSrvVar,ctx,true);


                                       }
                                       else
                                       {
                                           QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                           AbortException(msg);
                                       }
                                   }
                                   else
                                   {
                                       QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                       AbortException(msg);
                                   }
                               }
                               return 0;

                           }
                           else
                           {
                               QString msg = QString(u8"错误：函数 %1 语句 %2 字典值的多层列表非法范围，字典 %3 关键字 %4 对应值，其第 %5 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(curkey)).arg(i-listStart);
                               AbortException(msg);
                           }
                       }
                       else
                       {
                           QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                           AbortException(msg);
                       }
                   }
                   else
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                       AbortException(msg);
                   }
               }
           }

    return 0;
}
#endif


//赋值语句。所有的变量形式，浓缩为一句 pinvar : VARNAME ('[' listindex ']')* ('.'stMemVar)? ;
std::any ExprVisitor::visitAssignVar(PinParser::AssignVarContext *ctx)
{
    //分定义和赋值，如果是定义，则可以不需要 = right;如果是赋值，则
    std::string op = ctx->assignOp()->getText();
    AssignOpType optype = getOptype(op);

    PinParser::ExprContext *pExpr = ctx->rightvar()->expr();

    //获取变量名称。
    std::string varName = ctx->pinvar()->VARNAME()->getText();

    std::vector<PinParser::ListindexContext *> pListindex = ctx->pinvar()->listindex();

    PinParser::StMemVarContext * pStMem = ctx->pinvar()->stMemVar();

    pin_status_info pinStatus = getPinRunStatusData();

    SymNode* pSym = nullptr;

    //如果是定义变量
    if (pinStatus.status == DEFVAR_STATUS)
    {
        //不能是关键字
        if (isKeyWordTypeVar(varName))
        {
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 名称使用了pin内部保留关键字，还请改名！").arg(globalCurLine).arg(curStatement).
                arg(QStr(varName));
            AbortException(errmsg);
        }

        //变量是否已经存在
        //检查当前作用域是不是已经存在该变量，如果是则要报错。
        if (isLoaclVarAlreadyExist(varName))
        {
            //变量已经存在，不能重复定义
            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 在当前作用域已经存在，不能重复定义 !").arg(curLine).arg(curStatement).arg(QStr(varName));
            AbortException(msg);
            return 0;
        }

        if (optype != EQUAL_ASSIGN)
        {

            QString msg = QString(u8"错误：行号 %1 语句 %2 定义变量 %3 只能使用 = 号赋值，不能使用+= *=等符号。").arg(curLine).arg(curStatement).arg(QStr(varName));
            AbortException(msg);
            return 0;
        }

        //走定义流程
        switch (pinStatus.data) {

        case EXPR_INT:
        case EXPR_INT64:
        case EXPR_FLOAT:
        case EXPR_CHAR:
        case EXPR_WCHAR:
        case EXPR_STRING:
        case EXPR_U16STRING:
        case EXPR_LIST:
        case EXPR_MAP:
        case EXPR_DATE:
        case EXPR_FILE:
        case EXPR_EXCEL:
        case EXPR_BOOL:
        {

               if(pListindex.size() > 0 || pStMem != nullptr)
               {
                   QString msg = QString(u8"错误：行号 %1 语句 %2 变量%3 是 %4, 非法的定义语句 ！是否把赋值语句写错为定义 ？").arg(curLine)
                       .arg(curStatement).arg(QStr(varName)).arg(getExpeTypeValue(pinStatus.data));
                   AbortException(msg);
                   return 0;
               }
        }
            break;

        case EXPR_STRUCT:
        {
            //定义的流程中，不能出现结构体，这里永远不走。赋值可以走。定义结构体走 defstvar 语义
            QString msg = QString(u8"错误：行号 %1 语句 %2 变量%3 是 %4, 非法的定义语句 ！是否把赋值语句写错为定义 ？").arg(curLine)
                .arg(curStatement).arg(QStr(varName)).arg(getExpeTypeValue(pinStatus.data));
            AbortException(msg);
        }
            break;

        default:
            break;
        }

        //是在定义变量
       SymNode* newVar = new SymNode();
       #ifdef PIN_MEM_REF
             newTime();
        #endif
       newVar->name = varName;
       newVar->type = pinStatus.data;
       //加入到符号表中
       getPinSymTable()->append(newVar);
       pSym = newVar;

       //赋值写在下面。

    }
    else if(pinStatus.status == GLOBAL_DEFVAR_STATUS)
    {
        //不能是关键字
        if (isKeyWordTypeVar(varName))
        {
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 名称使用了pin内部保留关键字，还请改名！").arg(globalCurLine).arg(curStatement).
                arg(QStr(varName));
            AbortException(errmsg);
        }

        //检查全局作用域是不是已经存在该变量，如果是则要报错。
       if (isGloablVarAlreadyExist(varName))
       {
           //变量已经存在，不能重复定义
           QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 在全局作用域已经存在，不能重复定义！").arg(globalCurLine).arg(curStatement).
                            arg(QStr(varName));
           AbortException(errmsg);
           return 0;
       }

       if (optype != EQUAL_ASSIGN)
       {

           int linenum = ctx->getStart()->getLine();
           FUN_SYM_INFO* pGlobal = findFunBlock("quanju_dingyi");
           if(pGlobal != nullptr)
           {
               linenum += pGlobal->funNameLineNum - 1;//因为全局是个特例，其第1行是从quanju_dingyi本身开始的。
           }
           QString msg = QString(u8"错误：行号 %1 语句 %2 定义变量 %3 只能使用 = 号赋值，不能使用+= *=等符号。").arg(globalCurLine).arg(curStatement).arg(QStr(varName));
           AbortException(msg);
           return 0;
       }

       //走定义流程
       switch (pinStatus.data) {

       case EXPR_INT:
       case EXPR_INT64:
       case EXPR_FLOAT:
       case EXPR_CHAR:
       case EXPR_STRING:
       case EXPR_WCHAR:
       case EXPR_U16STRING:
       case EXPR_LIST:
       case EXPR_MAP:
       case EXPR_DATE:
       case EXPR_FILE:
       case EXPR_EXCEL:
       {

              if(pListindex.size() > 0 || pStMem != nullptr)
              {
                  QString msg = QString(u8"错误：行号 %1 语句 %2 变量%3 是 %4, 非法的定义语句 ！是否把赋值语句写错为定义 ？").arg(globalCurLine)
                      .arg(curStatement).arg(QStr(varName)).arg(getExpeTypeValue(pinStatus.data));
                  AbortException(msg);
                  return 0;
              }
       }
           break;

       case EXPR_STRUCT:
       {
           //定义的流程中，不能出现结构体，这里永远不走。赋值可以走。定义结构体走 defstvar 语义
           QString msg = QString(u8"错误：行号 %1 语句 %2 变量%3 是 %4, 非法的定义语句 ！是否把赋值语句写错为定义 ？").arg(globalCurLine)
               .arg(curStatement).arg(QStr(varName)).arg(getExpeTypeValue(pinStatus.data));
           AbortException(msg);
       }
           break;

       default:
           break;
       }

       //是在定义变量
      SymNode* newVar = new SymNode();
       #ifdef PIN_MEM_REF
                  newTime();
        #endif
      newVar->name = varName;
      newVar->type = pinStatus.data;
      //加入到符号表中
      insertGlobalSymTable(varName,newVar);
      pSym = newVar;
    }
    else
    {
        //如果是赋值语句
        //如果是在全局区，则直接报错。全区不能赋值，只能定义
        if(getPinRunStatus() == INTO_GLOBAL)
        {
            /*
            int offsetline = 0;
            FUN_SYM_INFO* pGlobal = findFunBlock("quanju_dingyi");
            if(pGlobal != nullptr)
            {
                offsetline = pGlobal->lineNum;
            }
            int line = ctx->pinvar()->getStart()->getLine() - 1;//因为全局是个特例，其第1行是从quanju_dingyi本身开始的。
            */
            QString msg = QString(u8"错误:行号 %1 语句 %2 quanju_dingyi 全局区域只能进行变量或结构体定义，不能进行赋值行为！").arg(globalCurLine).arg(QString::fromStdString(ctx->getText()));
            AbortException(msg);
        }
    }

    //下面开始赋值了。上面是如果是定义，则先把该定义的定义了，下面的逻辑统一走赋值。
    if(pSym == nullptr)
    {
        //说明一开始就是赋值,直接获取变量
        pSym = getVarFromSymTable(varName,ctx);
    }

    //下面开始统一进行赋值操作。
    switch(pSym->type)
    {

    case EXPR_INT:
    case EXPR_INT64:
    case EXPR_FLOAT:
    case EXPR_CHAR:
    case EXPR_BOOL:
    case EXPR_WCHAR:
    case EXPR_STRING:
    case EXPR_U16STRING:
    {
        //如果是基本变量
        if(pExpr == nullptr)
        {

            QString msg = QString(u8"错误：行号 %1 语句 %2 变量%3 是 %4 ，赋值右值 %5 不是可匹配的合法类型，不能把kong、列表、字典类型、不同的结构类型等赋值给变量 %3").arg(curLine)
                .arg(curStatement).arg(QStr(varName)).arg(getExpeTypeValue(pSym->type)).arg(QStr(ctx->rightvar()->getText()));
            AbortException(msg);
            return 0;
        }

#ifdef PIN_DEBUG
        std::cout << u8"表达式" << pExpr->getText() << std::endl;
#endif

        ExprValue value = std::any_cast<ExprValue>(visit(pExpr));

        //如果是字符串[]
        if((pSym->type == EXPR_STRING || pSym->type == EXPR_U16STRING) && (pListindex.size() > 0))
        {
            if(pListindex.size() == 1)
            {
                int index = -1;
                ExprValue indexExpr = std::any_cast<ExprValue>(visit(pListindex.at(0)->expr()));
                if(indexExpr.type == EXPR_INT || indexExpr.type == EXPR_INT64)
                {
                    index = indexExpr.value.vint;
                }

                if(pSym->type == EXPR_STRING)
                {
                    QByteArray* pByte = (QByteArray*)pSym->value.vpoint;
                    if(index >= 0 && index < pByte->size())
                    {
                        if(value.type == EXPR_CHAR)
                        {
                            pByte->operator [](index) = value.value.vchar;
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                .arg(QStr(varName)).arg(pByte->size()).arg(index);
                        AbortException(msg);
                    }
                }
                else if(pSym->type == EXPR_U16STRING)
                {
                    QString* pByte = (QString*)pSym->value.vpoint;
                    if(index >= 0 && index < pByte->size())
                    {
                        if(value.type == EXPR_CHAR)
                        {
                            pByte->operator [](index) = QChar(value.value.vchar);
                        }
                        else if(value.type == EXPR_WCHAR)
                        {
                            pByte->operator [](index) = QChar(value.value.vwchar);
                        }
                        else if(value.type == EXPR_INT)
                        {
                            if(value.value.vint >= 0 && value.value.vint <= 65535)
                            {
                                pByte->operator [](index) = QChar(value.value.vint);
                            }
                            else
                            {
                                QString msg = QString(u8"错误：行号 %1 语句 %2 宽字符使用整数合法赋值范围是0-65535，赋值是%3 无效越界 ").arg(curLine).arg(curStatement)
                                        .arg(value.value.vint);
                                AbortException(msg);
                            }
                        }
                        else
                        {
                            QString msg = QString(u8"错误：行号 %1 语句 %2 宽字符合法赋值类型是字符、宽字符、整数。当前赋值类型是 %3").arg(curLine).arg(curStatement)
                                    .arg(getExpeTypeValue(value.type));
                            AbortException(msg);
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                .arg(QStr(varName)).arg(pByte->size()).arg(index);
                        AbortException(msg);
                    }
                }
                return 0;
            }
            else
            {
                QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3[%4] 是字符类型，无法继续后续的[]操作！").arg(curLine).arg(QStr(ctx->getText())).
                                 arg(QStr(varName)).arg(QStr(pListindex.at(0)->getText()));
                AbortException(errmsg);
            }
        }

        //检查类型是否匹配，否则不继续，
        if (FillSymNodeByExpr(pSym, value, ctx, true, optype) < 0)
        {
            //这里是错误，中断继续，类型无法匹配。
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 变量 %3 是 %4，无法使用 %5 %6 进行赋值 ！").arg(curLine).arg(QStr(ctx->getText())).
                             arg(QStr(varName)).arg(getExpeTypeValue(pSym->type)).arg(getExpeTypeValue(value.type,&value)).arg(value.toString());
            AbortException(errmsg);
        }

        value.freeMem();

#ifdef PIN_DEBUG
        //赋值完成
        //QString msg = QString(u8"变量 %1 的值是 %2").arg(QString::fromStdString(varName)).arg(pSym->toString());
        //std::cout << msg.toStdString() << std::endl;
#endif
    }
        break;
    case EXPR_LIST:
    {
        //直接列表赋值给列表,只有结构体才能有.mem，[x].mem 必须要有[]
               if(pListindex.size() == 0)
               {
                   //不能有.mem，理由如上。
                   if(pStMem != nullptr)
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 列表 %3 不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(varName)).arg(QStr(pStMem->getText()));
                       AbortException(msg);
                       return 0;
                   }

                   //列表赋值给列表，右值列表以表达式方式进行赋值。
                   if(pExpr != nullptr)
                   {
                       //列表获取都是浅拷贝而来。
                       ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                       //必须是列表才行
                       if(rightExpr.type == EXPR_LIST && pSym->type == EXPR_LIST)
                       {
                           //因为是赋值，先把左边的释放,这里是计数判断释放，不一定真正释放。只有里面为0时，才会真正释放内存。
                           pSym->destory();

                           //和python保持一致：所有列表 map的赋值，默认都是浅拷贝。
                           pSym->value.vpoint = rightExpr.value.vpoint;

                           rightExpr.value.vpoint = nullptr;
                           //addListMapRefNum(pSym->value.vpoint);
                           //rightExpr.freeMap();
                           return 0;

                       }
                       else
                       {
                           QString msg = QString(u8"错误：函数 %1 语句 %2 不能把非列表类型语句 %3 赋值给列表 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pExpr->getText())).arg(QStr(varName));
                           AbortException(msg);
                       }
                   }
                   else if(ctx->rightvar()->list() != nullptr /*|| ctx->rightvar()->stRightVar() != nullptr 这里只能是列表*/)
                   {
                       //和上面的逻辑可以合并
                       //以lb_x = [1,2,4] 的方式直接赋值
                       ExprValue ret = std::any_cast<ExprValue>(visit(ctx->rightvar()->list()));

                       pSym->type = EXPR_LIST;

                       pSym->destory();

                       pSym->value.vpoint = ret.value.vpoint;
                       //这里是浅拷贝，直接把ret内存转移。转移一来一去，就不需要加引用
                       ret.value.vpoint=nullptr;

                       //addListMapRefNum(pSym->value.vpoint);


                       return 0;
                   }
                   else if(ctx->rightvar()->map() != nullptr)
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 不能把字典类型 %3 赋值给列表 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->map()->getText())).arg(QStr(varName));
                       AbortException(msg);
                       return 0;
                   }
                   else
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 不能把表达式类型 %3 赋值给列表 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(varName));
                       AbortException(msg);
                       return 0;
                   }

               }
               else
               {
                   //访问列表下面的元素
                   std::vector<PinParser::ListindexContext *> indexVec = pListindex;

                   //最开始是第一层列表，依次深入
                   std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;

                   for(int i=0,c=indexVec.size(); i<c; ++i)
                   {
                       ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                       //必须是整数类型.INT64不行。
                       if(ev.type == EXPR_INT)
                       {
                           //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                           int index = ev.value.vint;

                           if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                           {
                               ExprValue* ev = pchildlist->at(index);
                               if(ev->type == EXPR_LIST && i <(c-1))
                               {
                                   //这里就是开始解开列表，往里面一层一层的剥列表
                                   pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                                   continue;
                               }
#if 0
                               else if((i == (c-2)) && (ev->type == EXPR_STRING || ev->type == EXPR_U16STRING) )
                               {
                                    //倒数第二个是字符串，最后[]是修改字符串。
                                   //这里就是开始解开列表，往里面一层一层的剥列表
                                   QByteArray* pByte = (QByteArray*)ev->value.vpoint;
                                   if(pStMem == nullptr)
                                   {
                                       if(pExpr != nullptr)
                                       {
                                           int index = -1;
                                           ExprValue indexExpr = std::any_cast<ExprValue>(visit(indexVec.at(c-1)->expr()));
                                           if(indexExpr.type == EXPR_INT)
                                            {
                                                index = indexExpr.value.vint;
                                            }

                                            ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                            if(rightExpr.type == EXPR_CHAR)
                                            {
                                               if(index >= 0 && index < pByte->size())
                                               {
                                                    pByte->operator [](index) = rightExpr.value.vchar;
                                               }
                                            }
                                       }

                                   }
                               }
#endif
                               else if(i  == (c-1))
                               {
                                   if(pStMem == nullptr)
                                   {
                                       if(pExpr != nullptr)
                                       {
                                           //解到最后一层列表结果
                                           //因为是赋值，先把左边的释放。这个pExpr还是可能是列表
                                           ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                                           //不能是map，map目前不能赋值给列表
                                           if(rightExpr.type == EXPR_MAP)
                                           {
                                               QString msg = QString(u8"错误：函数 %1 语句 %2 不能把字典类型 %3 赋值给列表 %4 或其元素值!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pExpr->getText())).arg(QStr(varName));
                                               AbortException(msg);
                                               return 0;
                                           }

                                           //因为是赋值，先把左边的值释放。列表或字典，是共享内存，其余都是独立内存
                                           //需要走引用计数逻辑。
                                           //特别注意，必须外部调用freeMem，不能依赖FillExprByExpr内部，因为下面修改了类型。
                                           //之后的类型和之前的类型，可能不一样。
                                           ev->freeMem();
                                           ev->type = rightExpr.type;

                                           FillExprByExpr(ev,&rightExpr,ctx,true,optype);

                                           //内存浅拷贝掏空即可
                                           //ev->type = rightExpr.type;
                                           //ev->value = rightExpr.value;

                                           //ev不一定是列表,如果是列表，则加入计数
                                           //addListMapRefNum(*ev);




                                       }
                                       else if(ctx->rightvar()->list() != nullptr || ctx->rightvar()->stRightVar() != nullptr)
                                       {
                                           //以lb_x = [1,2,4] 的方式直接赋值
                                           ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                           ev->freeMem();

                                           //修改类型
                                           ev->type = rightExpr.type;

                                           //内存浅拷贝掏空即可
                                           //ev->type = rightExpr.type;
                                           //ev->value = rightExpr.value;

                                           //ev不一定是列表
                                           //addListMapRefNum(*ev);
                                           FillExprByExpr(ev,&rightExpr,ctx,optype);
                                       }
                                       else if(ctx->rightvar()->map() != nullptr)
                                       {
                                           QString msg = QString(u8"错误：函数 %1 语句 %2 不能把字典类型 %3 赋值给列表 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->map()->getText())).arg(QStr(varName));
                                           AbortException(msg);
                                           return 0;
                                       }

                                   }
                                   else
                                   {
                                       //继续按照结构体方式来解析
                                       if(ev->type == EXPR_STRUCT)
                                       {
                                           STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                           int index = getMemIndexFromStruct(pValue->structType, pStMem->getText(), ctx);
                                           if(index != -1)
                                           {
                                               //ExprValue ret;
                                               //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                               std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                               ExprValue* ret = (*pVec)[index];

                                               if(pExpr != nullptr)
                                               {
                                                   ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                                   //这里只能是基本元素类型。如果是字符串，里面会做浅拷贝move操作
                                                   FillExprByExpr(ret,&rightExpr,ctx,true,optype);
                                               }
                                               else
                                               {
                                                   QString msg = QString(u8"错误：行号 %1 语句 %2 不能把表达式类型 %3 赋值给结构体变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(pStMem->getText()));
                                                   AbortException(msg);
                                                   return 0;
                                               }

                                           }
                                           else
                                           {
                                               QString msg= QString(u8"错误：行号 %1 语句 %2 列表第 %3 个元素的结构体类型 %4 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(i).arg(QStr(pValue->structType)).arg(QStr(pStMem->getText()));
                                               AbortException(msg);
                                           }
                                       }
                                   }

                                   return 0;

                               }
                               else
                               {
                                   QString msg = QString(u8"错误：行号 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(curLine).arg(curStatement).arg(QStr(varName)).arg(i);
                                   AbortException(msg);
                               }
                           }
                           else
                           {
                               QString msg = QString(u8"错误：行号 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(curLine).arg(curStatement).arg(index);
                               AbortException(msg);
                           }
                       }
                       else
                       {
                           QString msg = QString(u8"错误：行号 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(curLine).arg(curStatement).arg(i);
                           AbortException(msg);
                       }
                   }

                   return 0;
               }


    }
    case EXPR_MAP:
    {

           PinParser::StMemVarContext* pMem = pStMem;
           std::vector<PinParser::ListindexContext *> indexVec = pListindex;
           std::string mapName = varName;

           //最开始是第一层列表，依次深入
           std::unordered_map<ExprValue, ExprValue*>* pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)pSym->value.vpoint;
           std::vector<ExprValue*>* pchildlist = nullptr;

           if(indexVec.size() == 0)
           {
               if(pMem != nullptr)
               {
                   QString msg = QString(u8"错误：行号 %1 语句 %2 字典 %3 不是结构体类型，无法访问成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(mapName)).arg(QStr(pMem->getText()));
                   AbortException(msg);

               }

               if(pExpr != nullptr)
               {
                   //列表获取都是浅拷贝而来。
                   ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                   //必须是字典才行
                   if(rightExpr.type == EXPR_MAP && pSym->type == EXPR_MAP)
                   {
                       //因为是赋值，先把左边的释放
                       pSym->destory();

                       //已经明确是字典，转移浅拷贝即可。
                       pSym->value.vpoint = rightExpr.value.vpoint;
                       rightExpr.value.vpoint = nullptr;
                       //addListMapRefNum(pSym->value.vpoint);

                       return 0;
                   }
                   else
                   {
                       QString msg = QString(u8"错误：函数 %1 语句 %2 不能把非字典类型语句 %3 赋值给字典 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(mapName));
                       AbortException(msg);
                   }
               }
               else if(ctx->rightvar()->map() != nullptr)
               {
                   //以zd_x = {k:y , k:y} 的方式直接赋值
                   ExprValue ret = std::any_cast<ExprValue>(visit(ctx->rightvar()->map()));

                   pSym->type = EXPR_MAP;

                   pSym->destory();

                   pSym->value.vpoint = ret.value.vpoint;
                   //这里是浅拷贝，直接把ret内存转移
                   ret.value.vpoint=nullptr;

                   //引用计数加1。不要加，一个减去，一个加，持平。
                   //addListMapRefNum(pSym->value.vpoint);

               }
               else
               {
                   QString msg = QString(u8"错误：函数 %1 语句 %2 不能把表达式类型 %3 赋值给字典 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(mapName));
                   AbortException(msg);
                   return 0;
               }

           }

           //以下必然是zd_1[x]访问的方式

           int i = 0;
           std::string curkey;
           ExprValue* pListElem;

                  for(int c=indexVec.size(); i<c; ++i)
                  {
                      ExprValue key = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                      //必须是整数类型.INT INT64 或 字符串
                      //if(key.type == EXPR_INT || key.type == EXPR_INT64 || key.type == EXPR_STRING)
                      if(key.isMapKeyType())
                      {

                          if(pchildmap != nullptr)
                          {
                              ExprValue* ev = nullptr;

                              auto it = pchildmap->find(key);

                              //找到
                              if(it != pchildmap->end())
                              {
                                  key.freeMem();

                                  ev = it->second;

                                  //还需要继续往下剥,而且还能继续剥
                                  if(ev->type == EXPR_MAP && (i< (c-1)))
                                  {
                                      //这里就是开始解开列表，往里面一层一层的剥列表
                                      pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)ev->value.vpoint;
                                      continue;
                                  }
                                  else if(ev->type == EXPR_LIST)
                                  {
                                      //特殊情况，遇到列表了
                                      //这里就是开始解开列表，往里面一层一层的剥列表
                                      //跳出map，开始解列表
                                      curkey = indexVec.at(i)->expr()->getText();
                                      pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                                      pListElem = ev;
                                      break;
                                  }
                                  else if(i == (c-1)) //不需要继续往下剥
                                  {
                                      if(pMem == nullptr)
                                      {
                                          //解到最后一层列表结果
                                          //因为是赋值，先把左边的释放。这个rightvar可能是list或map
                                          ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                          //因为是赋值，先把左边的值释放
                                          ev->freeMem();

                                          //转移掏空内存
                                          ev->type = rightExpr.type;

                                          FillExprByExpr(ev,&rightExpr,ctx,true,optype);
                                      }
                                      else
                                      {
                                          //继续访问结构体
                                          if(ev->type == EXPR_STRUCT)
                                          {
                                              STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                              int index = getMemIndexFromStruct(pValue->structType, pMem->getText(), ctx);
                                              if(index != -1)
                                              {
                                                  //ExprValue ret;
                                                  //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                                  std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                                  ExprValue* ret = (*pVec)[index];

                                                  if(pExpr != nullptr)
                                                  {
                                                       ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                                       //这里只能是基本元素类型。如果是字符串，里面会做浅拷贝move操作
                                                       FillExprByExpr(ret,&rightExpr,ctx,true,optype);
                                                  }
                                                  else
                                                  {
                                                       QString msg = QString(u8"错误：行号 %1 语句 %2 不能把表达式类型 %3 赋值给结构体变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(pMem->getText()));
                                                       AbortException(msg);
                                                       return 0;
                                                  }

                                              }
                                              else
                                              {
                                                  QString msg= QString(u8"错误：行号%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                                  AbortException(msg);
                                              }
                                          }
                                          else
                                          {
                                              QString msg = QString(u8"错误：行号 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(curLine).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                              AbortException(msg);
                                          }
                                      }
                                       return 0;
                                  }
                              }//没有找到map的key
                              else
                              {
                                   //没有发现元素，新加入一个元素
                                  //使用[key] = value 方式加入
                                  //如果是最后一层，则直接加入一个键值。
                                  if(i == (c-1))
                                  {
                                      ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                      //addListMapRefNum(rightExpr);
                                      //这个key如果是string,也是加了内存的，是否要释放？
                                      //这里加入到map中去，是一个浅拷贝。所以不能释放，是否返回导致map中的被破坏了。
                                      //所以不需要对key做释放。map析构的时候会自动释放。
                                      pchildmap->insert({key,rightExpr.shallowMoveCopy()});

                                      //不用加减计数，因为rightExpr本身可能要销毁，不加不加抵消

                                      return 0;
                                  }
                                  else
                                  {
                                      QString msg = QString(u8"错误：行号 %1 语句 %2 字典关键字key %3 对应值不存在，无法继续加入子项目！").arg(curLine).arg(curStatement).arg(QStr(indexVec.at(i)->expr()->getText()));
                                      AbortException(msg);
                                  }

                              }
                          }
                      }
                      else
                      {
                          QString msg = QString(u8"错误：行号 %1 语句 %2 字典%3 访问元素第 %4 个关键字 %5 类型错误，字典关键字索引只能是整数、字符、字符串类型!").arg(curLine).arg(curStatement).arg(QStr(mapName)).arg(i).arg(QStr(indexVec.at(i)->expr()->getText()));
                          AbortException(msg);
                      }
                  }

                  //遇到列表访问
                  if(pchildlist != nullptr)
                  {
                      ++i;//继续解访问后面的列表

                      //直接访问列表，后面没有更多[]号了
                      if(i == indexVec.size())
                      {
                          if(pMem != nullptr)
                          {
                              QString msg = QString(u8"错误：函数 %1 语句 %2 字典 %3 不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(pMem->getText()));
                              AbortException(msg);

                          }
                          //列表获取都是浅拷贝而来。
                          ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                          //必须是列表才行。这里不对，是可以修改类型的，不需要是列表。比如可以修改原来的列表为结构体。
                          pListElem->freeMem();
                           pListElem->type = rightExpr.type;
                           FillExprByExpr(pListElem,&rightExpr,ctx,true,optype);

                           return 0;

                      }

                     int listStart = i;
                      //最开始是第一层列表，依次深入
                     for(int c=indexVec.size(); i<c; ++i)
                      {
                          ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                          //必须是整数类型.INT64不行。
                          if(ev.type == EXPR_INT)
                          {
                              //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                              int index = ev.value.vint;

                              if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                              {
                                  ExprValue* ev = pchildlist->at(index);

                                  //还需要继续往下剥,而且还能继续剥
                                  if(ev->type == EXPR_LIST && (i< (c-1)))
                                  {
                                      //这里就是开始解开列表，往里面一层一层的剥列表
                                      pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                                      continue;
                                  }
                                 /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                                  {
                                      //这里就是开始解开列表，往里面一层一层的剥列表
                                      QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                                      AbortException(msg);
                                  }*/
                                  else if(i == (c-1)) //不需要继续往下剥
                                  {
                                      if(pMem == nullptr)
                                      {
                                          //解到最后一层列表结果
                                          //因为是赋值，先把左边的释放,字典没有限制
                                          ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

                                          //因为是赋值，先把左边的值释放
                                          ev->freeMem();
                                          ev->type = rightExpr.type;

                                          FillExprByExpr(ev, &rightExpr, ctx,true,optype);


                                      }
                                      else
                                      {
                                          //继续访问结构体
                                          if(ev->type == EXPR_STRUCT)
                                          {
                                              STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                              int index = getMemIndexFromStruct(pValue->structType, pMem->getText(), ctx);
                                              if(index != -1)
                                              {
                                                  //ExprValue ret;
                                                  //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                                  std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                                  ExprValue* ret = (*pVec)[index];

                                                  if(pExpr != nullptr)
                                                  {
                                                  ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                                                  //这里只能是基本元素类型。如果是字符串，里面会做浅拷贝move操作
                                                  FillExprByExpr(ret,&rightExpr,ctx,true,optype);
                                                  }
                                                  else
                                                  {
                                                      QString msg = QString(u8"错误：函数 %1 语句 %2 不能把表达式类型 %3 赋值给结构体变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(pMem->getText()));
                                                      AbortException(msg);
                                                      return 0;
                                                  }

                                              }
                                              else
                                              {
                                                  QString msg= QString(u8"错误：行号%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                                  AbortException(msg);
                                              }
                                          }
                                          else
                                          {
                                              QString msg = QString(u8"错误：行号 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(curLine).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                              AbortException(msg);
                                          }
                                      }
                                      return 0;

                                  }
                                  else
                                  {
                                      QString msg = QString(u8"错误：函数 %1 语句 %2 字典值的多层列表非法范围，字典 %3 关键字 %4 对应值，其第 %5 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(curkey)).arg(i-listStart);
                                      AbortException(msg);
                                  }
                              }
                              else
                              {
                                  QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                                  AbortException(msg);
                              }
                          }
                          else
                          {
                              QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                              AbortException(msg);
                          }
                      }
                  }

           return 0;
       }
    case EXPR_DATE:
    {

       tree::TerminalNode* pNil = ctx->rightvar()->EMPTY_VALUE();

       //如果是文件类型
       if (pExpr == nullptr && pNil == nullptr)
       {
           QString msg = QString(u8"错误：函数 %1 语句 %2 时间赋值右值 %3 不是合法类型，只能把时间变量、或 kong 赋值给时间类型变量 %4").arg(getCurFunQSName())
               .arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(varName));
           AbortException(msg);
           return 0;
       }

       if (pSym)
       {
           if (pExpr != nullptr)
           {
               //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
               ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));
                if (rightExpr.type == EXPR_DATE)
               {
                   pSym->destory();

                   pSym->value.vpoint = rightExpr.value.vpoint;

                   rightExpr.value.vpoint = nullptr;
               }
               else
               {
                   QString msg = QString(u8"错误：函数%1 语句 %2 给时间变量赋值时，右值 %3 必须是时间类型 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pExpr->getText()));
                   AbortException(msg);
               }
           }
           else if (pNil != nullptr)
           {
               //空赋值。
               pSym->destory();
               pSym->value.vpoint = new QDateTime();
#ifdef PIN_MEM_REF
               newTime();
#endif
           }

       }
       return 0;

       }

    case EXPR_FILE:
    {
           tree::TerminalNode* pNil = ctx->rightvar()->EMPTY_VALUE();

           //如果是文件类型
           if(pExpr == nullptr && pNil == nullptr)
           {
               QString msg = QString(u8"错误：行号 %1 语句 %2 文件赋值右值 %3 不是合法类型，只能把文件、字符串路径、或 kong 赋值给文件类型变量 %4").arg(curLine)
                       .arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(varName));
               AbortException(msg);
               return 0;
           }

           if(pSym)
           {
               if (pExpr != nullptr)
               {
                   //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                   ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                   if (rightExpr.type == EXPR_STRING)
                   {
                       if (rightExpr.value.vpoint == nullptr || ((QByteArray*)rightExpr.value.vpoint)->isEmpty())
                       {
                           QString msg = QString(u8"错误：行号 %1 语句 %2 给文件变量赋值时，文件路径 %3 不能是空字符串 !").arg(curLine).arg(curStatement).arg(QStr(pExpr->getText()));
                           AbortException(msg);
                       }

                       pSym->destory();

                       FILE_VALUE_DATA* pFileData = new FILE_VALUE_DATA();

                       QString filePath(*(QByteArray*)rightExpr.value.vpoint);

                       pFileData->pFileInfo = new QFileInfo(filePath);

                       QString absfilepath = pFileData->pFileInfo->absoluteFilePath();

   #ifdef PIN_MEM_REF
                       newTime(2);
                       qDebug() << absfilepath;
   #endif

                       pSym->value.vpoint = pFileData;

                       addListMapRefNum(pFileData);

                       rightExpr.freeMem();

                       return 0;

                   }
                   else if (rightExpr.type == EXPR_FILE)
                   {
                       pSym->destory();

                       pSym->value.vpoint = rightExpr.value.vpoint;
                       rightExpr.value.vpoint = nullptr;
                       //互相抵消
                       //addListMapRefNum(pSym->value.vpoint);
                       //rightExpr.freeMem();
                   }
                   else
                   {
                       QString msg = QString(u8"错误：行号 %1 语句 %2 给文件变量赋值时，文件路径 %3 必须是字符串类型 !").arg(curLine).arg(curStatement).arg(QStr(pExpr->getText()));
                       AbortException(msg);
                   }
               }
               else if (pNil != nullptr)
               {
                   //空赋值。
                   pSym->destory();
               }

           }
           return 0;
       }

    case EXPR_EXCEL:
    {
        tree::TerminalNode* pNil = ctx->rightvar()->EMPTY_VALUE();

        //如果是Excel类型
        if (pExpr == nullptr && pNil == nullptr)
        {
            QString msg = QString(u8"错误：行号 %1 语句 %2 Excel 表格赋值右值 %3 不是合法类型，只能把Excel、字符串路径、或 kong 赋值给Excel 类型变量 %4").arg(curLine)
                .arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(varName));
            AbortException(msg);
            return 0;
        }

        if (pSym)
        {
            if (pExpr != nullptr)
            {
                //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                ExprValue rightExpr = std::any_cast<ExprValue>(visit(pExpr));

                if (rightExpr.type == EXPR_STRING)
                {
                    //excel可以是空文件。
                   /* if (rightExpr.value.vpoint == nullptr && ((QByteArray*)rightExpr.value.vpoint)->isEmpty())
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 给Excel变量赋值时，文件路径 %3 不能是空字符串 !").arg(curLine).arg(curStatement).arg(QStr(pExpr->getText()));
                        AbortException(msg);
                    }
                    */
                    pSym->destory();

                    EXCEL_VALUE_DATA* pExcelFileData = new EXCEL_VALUE_DATA();
                    pExcelFileData->pDoc = new OpenXLSX::XLDocument;

#ifdef PIN_MEM_REF
                    newTime(2);
#endif
                    //如果是给的空字符串,则不初始化文件路径
                    if (rightExpr.value.vpoint != nullptr && !((QByteArray*)rightExpr.value.vpoint)->isEmpty())
                    {
                        pExcelFileData->excelFileName = ((QByteArray*)rightExpr.value.vpoint)->toStdString();
                    }

                    pSym->value.vpoint = pExcelFileData;

                    addListMapRefNum(pExcelFileData);

                    rightExpr.freeMem();

                    return 0;

                }
                else if (rightExpr.type == EXPR_EXCEL)
                {
                    pSym->destory();

                    pSym->value.vpoint = rightExpr.value.vpoint;
                    rightExpr.value.vpoint = nullptr;
                    //互相抵消
                    //addListMapRefNum(pSym->value.vpoint);
                    //rightExpr.freeMem();
                }
                else
                {
                    QString msg = QString(u8"错误：行号 %1 语句 %2 给Excel变量赋值时，文件路径 %3 必须是字符串类型 !").arg(curLine).arg(curStatement).arg(QStr(pExpr->getText()));
                    AbortException(msg);
                }
            }
            else if (pNil != nullptr)
            {
                //空赋值。
                pSym->destory();

                EXCEL_VALUE_DATA* pExcelFileData = new EXCEL_VALUE_DATA();
                pExcelFileData->pDoc = new OpenXLSX::XLDocument;
#ifdef PIN_MEM_REF
                newTime(2);
#endif
                pSym->value.vpoint = pExcelFileData;
                addListMapRefNum(pExcelFileData);
            }

        }
        return 0;
    }
    break;
    case EXPR_STRUCT:
    {
            PinParser::StRightVarContext* pStVar = ctx->rightvar()->stRightVar();
            if(pExpr == nullptr && pStVar == nullptr)
            {
                QString msg = QString(u8"行号 %1 语句 %2 结构体赋值右值 %3 不是合法类型，不能把列表或字典类型赋值给结构体 %4").arg(curLine)
                        .arg(curStatement).arg(QStr(ctx->rightvar()->getText())).arg(QStr(varName));
                AbortException(msg);
                return 0;
            }

            //PinParser::StructMemContext* pSm = pStMem;
            //是结构体成员变量的赋值。不能是定义,是定义也不保存，但是告警，还是做赋值流程
            //std::string stName = varName;

            if(pSym)
            {
                //是访问结构体的成员变量
                STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;

                if(pStMem != nullptr)
                {
                    int index = getMemIndexFromStruct(pValue->structType, pStMem->getText(), ctx);
                    if(index != -1)
                    {
                        //ExprValue ret;
                        //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                        ExprValue exprRet ;//= std::any_cast<ExprValue>(visit(pExpr));

                        if(pExpr != nullptr)
                        {
                            exprRet = std::any_cast<ExprValue>(visit(pExpr));
                        }
                        else if(pStVar != nullptr)
                        {
                             exprRet = std::any_cast<ExprValue>(visit(pStVar));
                        }

                        ExprValue* exprSrc = ((std::vector<ExprValue*>*)pValue->pValue)->operator [](index);

                        std::string op = ctx->assignOp()->getText();
                        AssignOpType optype = getOptype(op);

                        FillExprByExpr(exprSrc,&exprRet,ctx, true,optype);

                        //这里其实不需要，因为FillExprByExpr里面会调用释放，进行内存的转移。
                        exprRet.freeMem();

                        return 0;

                    }
                    else
                    {
                        QString msg= QString(u8"错误：行号 %1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pStMem->getText()));
                        AbortException(msg);
                    }
                }
                else
                {
                    //是访问结构体本身,使用 jg_1 = JG_1{1,2}; 的方式进行访问。
                    if(pStVar != nullptr)
                    {
                        //看看是否能够匹配，是不是同一个结构体
                        //是访问结构体的成员变量
                        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;

                        //必须是同一个结构体
                        if(pStVar->VARNAME()->getText() == pValue->structType)
                        {

                             ExprValue exprRet = std::any_cast<ExprValue>(visit(pStVar));

                             FillSymNodeByExpr(pSym, exprRet, ctx,true);

                             return 0;
                        }
                        else
                        {
                            QString errmsg = QString(u8"错误：行号 %1 语句 %2 结构体类型不一致，无法赋值。变量 %3 是 %4类型，表达式是 %5 类型！").arg(curLine).arg(curStatement)
                                    .arg(QStr(varName)).arg(QStr(pValue->structType)).arg(QStr(pStVar->VARNAME()->getText()));
                            AbortException(errmsg);
                        }
                    }
                    else if(pExpr != nullptr)
                    {
                        //是通过表达式返回结构体
                        ExprValue expr = std::any_cast<ExprValue>(visit(pExpr));
                        //看看是否能够匹配，是不是同一个结构体
                        //是访问结构体的成员变量
                        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;

                        if(expr.type == EXPR_STRUCT)
                        {
                            STRUCT_VALUE_DATA* pExprValue = (STRUCT_VALUE_DATA*)expr.value.vpoint;

                            //必须是同一个结构体
                            if(pExprValue->structType == pValue->structType)
                            {

                                 FillSymNodeByExpr(pSym, expr, ctx, true);

                                 return 0;
                            }
                        }

                            QString errmsg = QString(u8"错误：行号 %1 语句 %2 结构体类型不一致，无法赋值。变量 %3 是 %4类型，表达式 %5 是 %6 ！").arg(curLine).arg(curStatement)
                                    .arg(QStr(varName)).arg(QStr(pValue->structType)).arg(QStr(pExpr->getText())).arg(getExpeTypeValue(expr.type));
                            AbortException(errmsg);
                    }
                }

            }

            QString errmsg = QString(u8"错误：行号 %1 语句 %2 非法的结构体或成员赋值方式，请检查语法 !").arg(curLine).arg(curStatement);
            AbortException(errmsg);

            return 0;
        }
    }

    return 0;

}

int FillCppSymNodeByExpr(SymNode* pSym, int structId, ExprValue &expr,antlr4::ParserRuleContext *ctx)
{
    int ret = EXPR_to_Err;
    int type  = (structId << 16) | expr.type;

    switch(type)
   {
//        case PString_Struct_Id << 16 | EXPR_STRING:
//        {
//            ret = EXPR_string_to_Pstring;//字符串to qstring
//
//            STRUCT_VALUE_DATA* pData = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
//
//            if(pData->pCppObj.has_value())
//            {
//                pData->pCppObj = QString(*((QByteArray*)expr.value.vpoint));
//            }
//            else
//            {
//                pData->pCppObj = QString(*((QByteArray*)expr.value.vpoint));
//            }
//
//            expr.freeMem();
//        }
//        break;

    case REGEXP_Struct_ID << 16 | EXPR_U16STRING:
    case REGEXP_Struct_ID << 16 | EXPR_STRING:
    {
        ret = EXPR_string_to_Struct;//字符串to qstring
        STRUCT_VALUE_DATA* pData = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
        QRegularExpression& re = std::any_cast<QRegularExpression&>(pData->pCppObj);

        if(expr.type == EXPR_U16STRING)
        {
            //QRegularExpression re(*(QString*)expr.value.vpoint);
            //pData->pCppObj = re;
            re.setPattern(*(QString*)expr.value.vpoint);
        }
        else
        {
            //QRegularExpression re(QString(*(QByteArray*)expr.value.vpoint));
           // pData->pCppObj = re;
            re.setPattern(QString(*(QByteArray*)expr.value.vpoint));
        }

        std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pData->pValue;
        FillExprByExpr(pVec->at(0),&expr,ctx);


    }
        break;
        }
    return ret;
}

//结构体必须存在，如果是定义，前面在定义语句中已经定义过结构体变量了。
std::any ExprVisitor::visitAssignStOne(PinParser::AssignStOneContext *ctx)
{
    std::string stname = ctx->VARNAME()->getText();

    if(ctx->stFromExpr() != nullptr)
    {
        ExprValue expr = std::any_cast<ExprValue>(visit(ctx->stFromExpr()->expr()));

        //结构体的赋值。只能同类结构体互相赋值，不能不同结构体赋值，规定。
        std::string stVarName = ctx->VARNAME()->getText();

        SymNode* pSym = getVarFromSymTable(stVarName);

        if(pSym != nullptr )
        {

            //两个相同结构体的赋值。
            if(getStructVarTypeName(pSym) == getStructVarTypeName(expr))
            {
                pSym->destory();
                pSym->type = expr.type;
                FillSymNodeByExpr(pSym,expr, ctx);
               return 0;
            }

            int typeId = pSym->getStructTypeId();
            //继续检查是不是cpp底层的结构体，如果是，则还有一些可能赋值的可能
            if(typeId != Struct_Unkonwn_ID)
            {
                ////是使用表达式给底层cpp 类变量赋值。
                switch (typeId) {
                //case PString_Struct_Id: //目前只有字符串复杂给其
                //{
                //    //因为提前检查过类型，所以必然成功。
                //    if(expr.type == EXPR_STRING)
                //    {
                //        FillCppSymNodeByExpr(pSym,PString_Struct_Id,expr);
                //        return 0;
                //    }
                //}
                //    break;
                case REGEXP_Struct_ID:
                {
                     if(expr.type == EXPR_STRING || expr.type == EXPR_U16STRING)
                     {
                        FillCppSymNodeByExpr(pSym,REGEXP_Struct_ID,expr,ctx);
                        return 0;
            }
                }

                default:
                    break;
                }
            }
            //else 其余都是非法
            {
                QString errmsg = QString(u8"错误：行号 %1 语句 %2 结构体类型不一样，不能把 %3 的值，赋值给类型为%4 的变量 %5").arg(curLine).arg(curStatement)
                        .arg(getExpeTypeValue(expr.type, &expr)).arg(QStr(getStructVarTypeName(pSym))).arg(QStr(stVarName));
                AbortException(errmsg);
            }
        }
        else
        {
            QString errmsg = QString(u8"错误：行号 %1 语句 %2 找不到变量%3 或者不在当前可见作用域!").arg(curLine).arg(curStatement).arg(QStr(stVarName));
            AbortException(errmsg);
        }

    }
    else
    {

        std::vector<PinParser::ExprContext *> exprVec = ctx->expr();

        SymNode* pSym = getVarFromSymTable(stname, ctx);

        if(pSym->type == EXPR_STRUCT)
        {
            STRUCT_VALUE_DATA* pStValue = (STRUCT_VALUE_DATA*)(pSym->value.vpoint);

            std::string stTypeName = pStValue->structType;

            //结构体是在全局中
            SymNode* pStType = getVarFromGlobalSymTable(stTypeName,ctx,1);

            //看看结构体的参数和赋值参数能否匹配
            std::vector<std::string>* paraList =  (std::vector<std::string>*)(pStType->value.vpoint);

            std::vector<ExprValue*>* valueList = (std::vector<ExprValue*>*)pStValue->pValue;

            if(valueList != nullptr)
            {
            int paraNum = paraList->size()/2 ;

            if(paraNum == exprVec.size())
            {
                std::vector<ExprValue*>::iterator it = valueList->begin();

                //开始逐一赋值结构体变量。
                for(int i=0,c=exprVec.size(); i<c; ++i)
                {
                    ExprValue ev = std::any_cast<ExprValue>(visit(exprVec.at(i)));

                    //如果类型相等，则直接赋值。//虽然类型不相等，但是可以转换，也转换一下。文件路径转文件
                    if((*it)->type == ev.type || (exprTypeMatch((*it)->type, ev.type) >= 0))
                    {
                        //把原来的释放。
                        (*it)->freeMem();
                        //it->value = ev.value;
                        FillExprByExpr(*it,&ev,ctx);
                    }
                    else
                    {


                        QString msg = QString(u8"错误：行号 %1 语句 %2 结构体第%3 个参数 %4 需要%5，赋值类型是%6, 无法匹配！").arg(curLine).arg(curStatement).arg(i+1).arg(QString::fromStdString(paraList->at(i))).arg(getExpeTypeValue((*it)->type)).arg(getExpeTypeValue(ev.type));
                        AbortException(msg);
                    }
                    ++it;

                }

            }
            else
            {
                QString msg = QString(u8"错误：行号 %1 语句 %2 结构体 %3 类型 %4 需要 %5个参数，赋值结构体有%6个参数，个数无法匹配!").arg(curLine).arg(curStatement).arg(QStr(stname))
                        .arg(QStr(stTypeName)).arg(paraNum).arg(exprVec.size());

                        AbortException(msg);
            }
        }
    }
    }


    return 0;
}



std::any ExprVisitor::visitAndExpr(PinParser::AndExprContext* ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if (leftExpr.type == EXPR_BOOL && rightExpr.type == EXPR_BOOL)
        {
            ret.value.vbool = (leftExpr.value.vbool && rightExpr.value.vbool);
        }
        else if (leftExpr.type != EXPR_BOOL)
        {
            QString msg = QString(u8"错误:行号 %1 错误类型进行 and 布尔逻辑并且计算。\n语句 %2 表达式 %3 不是布尔逻辑类型，无法进行逻辑操作！").arg(curLine).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(exprVec.at(0)->getText()));
            AbortException(msg);
        }
        else if (rightExpr.type != EXPR_BOOL)
        {
            QString msg = QString(u8"错误:行号 %1 错误类型进行 and 布尔逻辑并且计算。\n语句 %2 表达式 %3 不是布尔逻辑类型，无法进行逻辑操作！").arg(curLine).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(exprVec.at(1)->getText()));
            AbortException(msg);
        }
        else
        {
           QString msg = QString(u8"错误:行号 %1 错误类型进行 and 布尔逻辑并且计算。\n语句 %2 表达式不是布尔逻辑类型，无法进行逻辑操作！").arg(curLine).arg(QString::fromStdString(ctx->getText()));
           AbortException(msg);

        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

void inExprFun(ExprValue& leftExpr, ExprValue& expr, ExprValue& ret,antlr4::ParserRuleContext* ctx)
{
    switch (leftExpr.type)
    {
    case EXPR_INT:
    case EXPR_INT64:
    case EXPR_STRING:
    case EXPR_U16STRING:
    case EXPR_CHAR:
    case EXPR_WCHAR:
    {
        if (expr.type == EXPR_LIST)
        {
            std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)expr.value.vpoint;

            for (int i = 0, s = pList->size(); i < s; ++i)
            {
                if (EQUAL_STATUS == CompareExprAndExpr(leftExpr, *(pList->at(i)), false))
                {
                    ret.value.vbool = true;
                    break;
                }
            }
        }
        else if (expr.type == EXPR_MAP)
        {
            std::unordered_map<ExprValue, ExprValue*>* pMap = (std::unordered_map<ExprValue, ExprValue*>*)expr.value.vpoint;

            ret.value.vbool = (pMap->find(leftExpr) != pMap->end());
        }
        else
        {
            int type  = expr.type << 16 | leftExpr.type;

            switch(type)
            {
                case EXPR_STRUCT << 16 | EXPR_STRING:
                {
            STRUCT_VALUE_DATA* pSrc = (STRUCT_VALUE_DATA*)expr.value.vpoint;

            std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)pSrc->pValue;

            if (pList != nullptr)
            {
                SymNode* pStructDesc = getVarFromGlobalSymTable(pSrc->structType, ctx, 1);
                std::vector<std::string>* pParalist = (std::vector<std::string>*)pStructDesc->value.vpoint;
                if (pParalist != nullptr && pParalist->size() > 0)
                {
                    std::string eleName = leftExpr.getString();
                    for (int i = 0, s = pParalist->size() / 2; i < s; ++i)
                    {
                        if (eleName == pParalist->at(i))
                        {
                            ret.value.vbool = true;
                            break;
                        }
                    }
                }
            }
        }
                break;

                case EXPR_STRING << 16 | EXPR_STRING:
                {
                    QByteArray* subStr =  (QByteArray*)leftExpr.value.vpoint;

                    QByteArray* str =  (QByteArray*)expr.value.vpoint;

                    ret.value.vbool = (-1 != str->indexOf(*subStr));
    }
    break;


                case EXPR_STRING << 16 | EXPR_CHAR:
                {
                    QByteArray* str =  (QByteArray*)expr.value.vpoint;

                    ret.value.vbool = str->contains(leftExpr.value.vchar);
                }
                break;

                case EXPR_STRING << 16 | EXPR_WCHAR:
                {
                    QString str =  QString(*(QByteArray*)expr.value.vpoint);

                    QString substr;
                    substr.append(QChar(leftExpr.value.vwchar));

                    ret.value.vbool = str.contains(substr);
                }
                break;

                case EXPR_STRING << 16 | EXPR_U16STRING:
                {
                    QString str =  QString(*(QByteArray*)expr.value.vpoint);

                    ret.value.vbool = str.contains(*(QString*)leftExpr.value.vpoint);
                }
                break;

                case EXPR_U16STRING << 16 | EXPR_U16STRING:
                {
                    QString* subStr =  (QString*)leftExpr.value.vpoint;

                    QString* str =  (QString*)expr.value.vpoint;

                    ret.value.vbool = str->contains(*subStr);
                }
                break;


                case EXPR_U16STRING << 16 | EXPR_WCHAR:
                {
                    QString* str =  (QString*)expr.value.vpoint;

                    ret.value.vbool = str->contains(QChar(leftExpr.value.vwchar));
                }
                break;

                case EXPR_U16STRING << 16 | EXPR_CHAR:
                {
                    QString* str =  (QString*)expr.value.vpoint;

                    ret.value.vbool = str->contains(QChar(leftExpr.value.vchar));
            }
                break;

                case EXPR_U16STRING << 16 | EXPR_STRING:
                {
                    QString* str =  (QString*)expr.value.vpoint;
                    QString substr =  QString(*(QByteArray*)leftExpr.value.vpoint);

                    ret.value.vbool = str->contains(substr);
        }
                break;
    }
        }
    }
    break;

    default:
        ret.value.vbool = false;
        break;
    }
}


//变量是否在list or key 中
std::any ExprVisitor::visitInExpr(PinParser::InExprContext* ctx)
{
    ExprValue expr = std::any_cast<ExprValue>(visit(ctx->rightvar()));

    switch (expr.type)
    {
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_STRUCT:
    case EXPR_STRING:
    case EXPR_U16STRING:
    {
        break;
    }
        default:
        {
        expr.freeMem();
            QString errmsg = QString(u8"错误：行号 %1 语句 %2 只有列表、字典、结构体、字符串可以做 in 操作对象！变量或表达式 %3 类型是 %4").arg(curLine).arg(curOnelineSrcStatement)
            .arg(QStr(ctx->rightvar()->getText())).arg(getExpeTypeValue(expr.type, &expr));
        AbortException(errmsg);
            AbortException(errmsg);
        return 0;
    }
    }

    ExprValue ret;
    ret.type = EXPR_BOOL;
    ret.value.vbool = false;
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr()));

    inExprFun(leftExpr, expr, ret,ctx);
    #if 0
    switch (leftExpr.type)
    {
    case EXPR_INT:
    case EXPR_INT64:
    case EXPR_STRING:
    case EXPR_U16STRING:
    case EXPR_CHAR:
    case EXPR_WCHAR:
    {
        if (expr.type == EXPR_LIST)
        {
            std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)expr.value.vpoint;

            for (int i = 0, s = pList->size(); i < s; ++i)
            {
                if (EQUAL_STATUS == CompareExprAndExpr(leftExpr, *(pList->at(i)), false))
                {
                    ret.value.vbool = true;
                    break;
                }
            }
        }
        else if (expr.type == EXPR_MAP)
        {
            std::unordered_map<ExprValue, ExprValue*>* pMap = (std::unordered_map<ExprValue, ExprValue*>*)expr.value.vpoint;

            ret.value.vbool = (pMap->find(leftExpr) != pMap->end());
        }
        else if (expr.type == EXPR_STRUCT && leftExpr.type == EXPR_STRING)
        {
            STRUCT_VALUE_DATA* pSrc = (STRUCT_VALUE_DATA*)expr.value.vpoint;

            std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)pSrc->pValue;

            if (pList != nullptr)
            {
                SymNode* pStructDesc = getVarFromGlobalSymTable(pSrc->structType, ctx, 1);
                std::vector<std::string>* pParalist = (std::vector<std::string>*)pStructDesc->value.vpoint;
                if (pParalist != nullptr && pParalist->size() > 0)
                {
                    std::string eleName = leftExpr.getString();
                    for (int i = 0, s = pParalist->size() / 2; i < s; ++i)
                    {
                        if (eleName == pParalist->at(i))
                        {
                            ret.value.vbool = true;
                            break;
                        }
                    }
                }
            }
        }
    }
    break;

    default:
        ret.value.vbool = false;
        break;
    }
#endif
    leftExpr.freeMem();
    expr.freeMem();
    return ret;
}


//not in in的反义。
std::any ExprVisitor::visitNotinExpr(PinParser::NotinExprContext *ctx)
{
    ExprValue expr = std::any_cast<ExprValue>(visit(ctx->rightvar()));
    switch (expr.type)
    {
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_STRUCT:
    case EXPR_STRING:
    case EXPR_U16STRING:
    {
        break;
    }
        default:
        {
        expr.freeMem();
            QString errmsg = QString(u8"错误：行号 %1 语句 %2 只有列表、字典、结构体、字符串可以做 not in 操作对象！变量或表达式 %3 类型是 %4").arg(curLine).arg(curOnelineSrcStatement)
            .arg(QStr(ctx->rightvar()->getText())).arg(getExpeTypeValue(expr.type, &expr));
        AbortException(errmsg);
        return 0;
    }
    }

    ExprValue ret;
    ret.type = EXPR_BOOL;
    ret.value.vbool = false;
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr()));

    inExprFun(leftExpr, expr, ret,ctx);

    leftExpr.freeMem();
    expr.freeMem();

    ret.value.vbool = !ret.value.vbool;
    return ret;
}

std::any ExprVisitor::visitNotExpr(PinParser::NotExprContext* ctx)
{
    PinParser::ExprContext* pExpr = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (pExpr != nullptr)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(pExpr));

        if (leftExpr.type == EXPR_BOOL)
        {
            ret.value.vbool = !leftExpr.value.vbool;
        }
        else
        {
            QString msg = QString(u8"错误类型进行 not 逻辑非计算：函数 %1 语句 %2 表达式不是逻辑类型，无法进行操作！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
            AbortException(msg);

        }

        leftExpr.freeMem();
    }

    return ret;
}

std::any ExprVisitor::visitOrExpr(PinParser::OrExprContext* ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if (leftExpr.type == EXPR_BOOL && rightExpr.type == EXPR_BOOL)
        {
            ret.value.vbool = (leftExpr.value.vbool || rightExpr.value.vbool);
        }
        else
        {
            QString msg = QString(u8"错误类型进行 or 逻辑或计算：函数 %1 语句 %2 表达式不是逻辑类型，无法进行操作！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
            AbortException(msg);

        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

//不等于比较
std::any ExprVisitor::visitUnequalExpr(PinParser::UnequalExprContext *ctx)
{
    std::vector<PinParser::ExprContext *> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if(exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (EQUAL_STATUS == status)
        {
            ret.value.vbool = false;
        }
        else
        {
            ret.value.vbool = true;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

std::any ExprVisitor::visitEqualExpr(PinParser::EqualExprContext *ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (EQUAL_STATUS == status)
        {
            ret.value.vbool = true;
        }
        else
        {
            ret.value.vbool = false;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

std::any ExprVisitor::visitGreaterExpr(PinParser::GreaterExprContext *ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (GREATER_STATUS == status)
        {
            ret.value.vbool = true;
        }
        else
        {
            ret.value.vbool = false;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}
std::any ExprVisitor::visitLessExpr(PinParser::LessExprContext *ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (LESS_STATUS == status)
        {
            ret.value.vbool = true;
        }
        else
        {
            ret.value.vbool = false;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}
std::any ExprVisitor::visitLessEqualExpr(PinParser::LessEqualExprContext *ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (LESS_STATUS == status || EQUAL_STATUS == status)
        {
            ret.value.vbool = true;
        }
        else
        {
            ret.value.vbool = false;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}
std::any ExprVisitor::visitGreaterEqualExpr(PinParser::GreaterEqualExprContext *ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ret.type = EXPR_BOOL;

        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        int status = CompareExprAndExpr(leftExpr, rightExpr);
        if (GREATER_STATUS == status || EQUAL_STATUS == status)
        {
            ret.value.vbool = true;
        }
        else
        {
            ret.value.vbool = false;

            if (status == CAN_NOT_CMP)
            {
                QString msg = QString(u8"错误类型进行对比：函数 %1 语句 %2 表达式或变量无法进行对比！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(msg);
            }
        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

#if 0
//访问bool 变量的值
std::any ExprVisitor::visitBoolVarExpr(PinParser::BoolVarExprContext *ctx)
{
    std::string name = ctx->getText();

    SymNode* pSym = getVarFromSymTable(name);

    ExprValue ret;

    if(pSym == nullptr){

        QString msg = QString(u8"函数 %1 语句 %2 中存在未定义的变量 %3").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(name));

        AbortException(msg);

        ret.type = EXPR_ERR;
    }
    else
    {
        ret.type = pSym->type;
        ret.value.vint64 = pSym->value.vint64; //按最大的走

    }

    return ret;
}
#endif

std::any ExprVisitor::visitBoolValueExpr(PinParser::BoolValueExprContext *ctx)
{
    std::string value = ctx->getText();
    const char* pChar = value.data();

    ExprValue ret;

    ret.type = EXPR_BOOL;
    ret.value.vbool = (pChar[0] == 'z' || pChar[0] == 't');//zhen 或 true

    return ret;
}

#if 0
std::any ExprVisitor::visitParenthesesBoolExpr(PinParser::ParenthesesBoolExprContext *ctx)
{
    return visit(ctx->boolExpr());
}
#endif


#if 0
std::any ExprVisitor::visitBoolAssign(PinParser::BoolAssignContext *ctx)
{
    int c = ctx->BOOL().size();

    for(int i=0; i < c; ++i)
    {
        //判断是定义还是赋值
        std::string varName = ctx->BOOL(i)->getText();
        SymNode *pVar = nullptr;

        if(DEFVAR_STATUS == getPinRunStatus())
        {
            //检查当前作用域是不是已经存在该变量，如果是则要报错。
            if(isLoaclVarAlreadyExist(varName))
            {
                //变量已经存在，不能重复定义
                QString errmsg = QString(u8"错误语句 %1 变量 %2 在当前作用域已经存在，不能重复定义！").arg(QString::fromStdString(ctx->getText())).
                                 arg(QString::fromStdString(varName));
                std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

                std::rethrow_exception(eptr);
                return 0;
            }
            //是在定义变量
            SymNode *newVar = new SymNode();
            newVar->name = varName;
            newVar->type = getVarTypeByName(varName);
            //加入到符号表中
            getPinSymTable()->append(newVar);
            pVar = newVar;
        }
        else
        {
            pVar = getVarFromSymTable(varName);
        }

        if(pVar == nullptr){
            //这里要退出，说明是错误，遇到没有定义的变量
            std::cout << u8"错误变量没有定义或者在合法作用域内没有该变量! " << varName << std::endl;
            QString errmsg = QString(u8"错误语句 %1 变量 %2 没有定义 ！").arg(QString::fromStdString(ctx->getText())).
                             arg(QString::fromStdString(varName));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);
            return 0;
        }

        int type = getVarTypeByName(varName);

        //std::cout << u8"开始赋值函数调用" << ctx->getText() << std::endl;
        std::cout << u8"表达式" << ctx->boolExpr(i)->getText() << std::endl;

        //访问赋值语句
        ExprValue value = std::any_cast<ExprValue>(visit(ctx->boolExpr(i)));

        //std::cout << u8"变量值是";
        //value.print(ctx->expr(i)->getText());

        //检查类型是否匹配，否则不继续，
        if(FillSymNodeByExpr(pVar,value,true) < 0)
        {
            //这里是错误，中断继续，类型无法匹配。
            QString errmsg = QString(u8"错误语句 %1 变量 %2 无法使用值 %3 进行赋值").arg(QString::fromStdString(ctx->getText())).
                             arg(QString::fromStdString(varName)).arg(value.toString());
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);
            break;
        }
        //赋值完成
        QString msg = QString(u8"变量 %1 的值是 %2").arg(QString::fromStdString(varName)).arg(value.toString());
        std::cout << msg.toStdString() << std::endl;
    }


    return 0;
}
#endif

extern std::atomic<bool> shouldExit;

//遇到作用域{} 
std::any ExprVisitor::visitBlock(PinParser::BlockContext* ctx)
{
	#ifdef PIN_DEBUG
    std::cout << u8"-- 进入作用域块 " << ctx->getText() << std::endl;
	#endif

    if (shouldExit) {
        QString msg = QString(u8"用户中断脚本继续执行,终止执行 ...");
        AbortException(msg);
        return -1;
    }

    //进入函数的第一个块
    if (getPinRunStatus() == INTO_FUN_FIRST_BLOCK_SCOPE)
    {
        popStatus();

        //由于是函数的第一个作用域，前面在函数调用过程中已经加入了，这里就不加入新的作用域。
    }
    else
    {
        //不是函数的第一个作用域，则要加入新作用域。
        //保证形参参数的定义，是在函数根作用域的后面。
        //加入一个作用域
        SymNode* node = new SymNode;
		#ifdef PIN_MEM_REF
            newTime();
#endif
        node->type = SCOPE_SYM;
        //作用域反而是没有名称的。
        getPinSymTable()->push_back(node);
    }

	std::vector<PinParser::StatementContext*> stateVec = ctx->statement();

    //逐条执行语句
	for (auto v : stateVec)
	{
        //一定进入return模式，后续不再执行
        if (getPinRunStatus() == FUNCTION_RET)
        {
            //遇到函数的return语句了，不再继续后续语句执行
            break;
        }

        //如果遇到break语句,前面做了判断，一定是在for循环中。
        if (getPinRunStatus() == INTO_BREAK)
        {
            //遇到函数循环的break语句，则不继续循环了
            break;
        }

        if (getPinRunStatus() == INTO_CONTINUE)
        {
            //遇到函数循环的continue语句，则不继续循环了
            break;
        }

		visit(v);
	}

	//把当前调用栈打印出来
    //printStackInfo();

    //退出作用域的时候，需要把当前作用域上定义的变量删除掉。
    //这里有个特殊情况，就是函数的形参，也是在根作用域之上。
    deleteCurScope();

	return 0;
}


//访问器是从这里开始的。
std::any ExprVisitor::visitProgram(PinParser::ProgramContext* ctx) 
{
#ifdef PIN_DEBUG
	std::cout << "--0 " << ctx->getText() << std::endl;
#endif

    //全局访问完毕后
	//这里一定要继续往下面写，否则会导致后续的语句无法访问到。
	return visitChildren(ctx);
}

//入口函数
//std::any ExprVisitor::visitMainFun(PinParser::MainFunContext* ctx)
//{
//	////立刻把函数入栈。
//	//SymNode node;
//	//node.name = "hs_rukou";
//	//node.type = FUN_SYM; 
//	//getPinSymTable()->append(node);
//	std::cout << "--info" << ctx->toString() << std::endl;
//	std::cout << "--main " << ctx->getText() << std::endl;
//
//	//如果有函数体，则继续访问
//	if (ctx->block() != nullptr)
//	{
//		visit(ctx->block());
//	}
//	return 0;
//}

//定义函数。这里怕是永远都不走了。这里要走，不然发现不了函数了。
std::any ExprVisitor::visitFunction(PinParser::FunctionContext* ctx)
{
	#ifdef PIN_DEBUG
    std::cout << "--visit def fun " << ctx->VARNAME()->getText() << std::endl;
	std::cout << "--visit fun block " << ctx->block()->getText() << std::endl;
#endif
    visitChildren(ctx);
	return 0;
}

//函数的参数表达式，求值。进入这里，一定是在求值函数的参数
std::any ExprVisitor::visitArgument(PinParser::ArgumentContext *ctx)
{
    return 0;
}

void destory_temp_para_ref(QList<void*>* &temp_para_ref)
{
    if(temp_para_ref != nullptr)
    {
        for(int i=0,c = temp_para_ref->size(); i<c; ++i)
        {
            subListMapRefNum(temp_para_ref->at(i));
        }
        delete temp_para_ref;
        temp_para_ref = nullptr;
    }
}

//获取变量名称
std::string getPinvarName(PinParser::PinvarContext* ctx)
{

    return ctx->VARNAME()->getText();

    /*
    //基础变量，包含结构体
    if(ctx->basevar() || ctx->STRUCT_ID() || ctx->FILE_ID() || ctx->DATE_ID())
    {
        return ctx->getText();
    }

    if(ctx->structMem())
    {
        return ctx->structMem()->STRUCT_ID()->getText();
    }

    if(ctx->accesslist())
    {
        return ctx->accesslist()->LIST_ID()->getText();
    }

    if(ctx->accessmap())
    {
        return ctx->accessmap()->MAP_ID()->getText();
    }

    QString msg = QString(u8"错误：函数 %1 语句 %2 未知的变量 %3").arg(getCurFunQSName()).arg(curStatement).arg(QStr(ctx->getText()));
    AbortException(msg);
    return "";
    */
}


//通过对象去调用后续的方法。
std::any ExprVisitor::visitCallQtFun(PinParser::RealCallFunContext* ctx, PinParser::WithRetCallFunContext* ctxParent, ExprValue& objExpr, std::string funName, PinParser::ArgumentListContext* pArglist, bool isBaoFunCall, int flag)
{

    CPP_FUN_INFO* fun_info = findCppFun(objExpr, funName, ctx);


    std::vector<int>* pParaList = fun_info->paraList;

    //检查调用参数个数能否匹配
    if (pParaList == nullptr && pArglist == nullptr)
    {
        //没有参数，匹配。
    }
    else if (pParaList != nullptr && pArglist != nullptr)
    {
        std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

        //有可选参数时，必须是少于1个或2个的情况。
        if (pParaList->back() == EXPR_INT_OPTION)
        {
            int num = pParaList->size() - argVec.size();
            if (num == 1 || num == 2)
            {
                //ok。可选的int参数，没有给值。
            }
            else
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！函数%3 最多接收 %4 个参数！这里却给了 %5 个参数！").arg(curLine).arg(curStatement).arg(QString::fromStdString(funName)).arg(pParaList->size() - 1).arg(argVec.size());
                AbortException(errmsg);
            }
        }
        else if (pParaList->back() == EXPR_PARA_DYNANIC)
        {
            //是动态参数，只检查参数个数的范围是否满足。
            if (argVec.size() > pParaList->operator[](1) || argVec.size() < pParaList->operator[](0))
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！函数%3 可接收 %4-%5 个参数！这里却给了 %6 个参数！").arg(curLine).arg(curStatement).arg(QString::fromStdString(funName)).arg(pParaList->operator[](0)).arg(pParaList->operator[](1)).arg(argVec.size());
                AbortException(errmsg);
            }
        }
        else if (pParaList->size() != argVec.size())
        {

            QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！函数%3 最多接收 %4 个参数！这里却给了 %5 个参数！").arg(curLine).arg(curStatement).arg(QStr(funName)).arg(pParaList->size()).arg(argVec.size());
            AbortException(errmsg);
        }
    }
    else
    {
        //一个有，另一个没有。
        if (pParaList != nullptr)
        {
            //如果调用函数没有给参数，而函数定义可以接受一个动态参数，则也是可以的。
            if (pParaList->back() == EXPR_INT_OPTION && (pArglist == nullptr || pArglist->argument().size() == 0))
            {
                //ok
            }
            else if ((pParaList->back() == EXPR_PARA_DYNANIC) && (pArglist == nullptr || pArglist->argument().size() == 0))
            {
                //是动态参数，目前只有toHex一个函数。
            }
            else
            {
                int num = -1;
                int less = -1, max = -1;

                QString paraNum;

                int getParaNum;

                if (pParaList->back() == EXPR_INT_OPTION)
                {
                    num = pParaList->size() - 1;
                    paraNum = QString::number(num);
                }
                else if (pParaList->back() == EXPR_PARA_DYNANIC && pParaList->size() >= 2)
                {
                    less = pParaList->at(0);
                    max = pParaList->at(1);

                    paraNum = QString("%1 到 %2").arg(less).arg(max);
                }
                else
                {
                    paraNum = QString::number(pParaList->size());
                }

                if (nullptr == pArglist)
                {
                    getParaNum = 0;
                }
                else
                {
                    getParaNum = pArglist->argument().size();
                }

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数和其定义无法匹配！%3 可接受 %4 个函数！\n调用却给了 %5 个参数！").arg(curLine).
                    arg(curStatement).arg(QStr(funName)).arg(paraNum).arg(getParaNum);
                AbortException(errmsg);
            }
        }
        else
        {
            //其余都是非法情况了。
            int num = 0;
            if (pParaList == nullptr || pParaList->size() == 0)
            {
                num = 0;
            }
            else
            {
                if (pParaList->back() == EXPR_INT_OPTION)
                {
                    num = pParaList->size() - 1;
                }
                else
                {
                    num = pParaList->size();
                }
            }
            std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

            QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数和其定义无法匹配！函数 %3 最多需要 %4个参数! 这里却给了 %5 个参数").arg(curLine).arg(curStatement).arg(QStr(funName)).arg(num).arg(argVec.size());
            AbortException(errmsg);

            return 0;
        }
    }

    QList<SymNode*> paraSymList;

    QList<ExprValue*>* callFunStack = getFunCallStack();

    int stackSize = 2; //对象和名称，多2个参数

    int objIndex = 0; //把对象在栈中的位置记住。

    //先把函数的参数求值一下，现在还是在调用者的栈上面，务必特别注意。
    if (pArglist != nullptr)
    {

        //如果有参数，进入求参数值，而且把结构入栈的情况
        std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

        stackSize += argVec.size();

        for (PinParser::ArgumentContext* arg : argVec)
        {
            //cpp qt 调用函数上，只能有变量做参数，不能有函数或回调函数做参数。

            if (arg->rightvar() == nullptr)
            {

                QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 不能使用函数或回调函数 %4做参数！").arg(curLine).arg(curStatement).arg(QStr(funName)).arg(QStr(arg->getText()));
                AbortException(errmsg);
                break;
            }
            //进入表达式求值
            ExprValue expr = std::any_cast<ExprValue>(visit(arg->rightvar()));

            //这里不需要加入计数，因为expr中已经加1了，而且这里没有释放。后续只存在释放。
            //这里加入依次计数，因为函数调用完毕后，要统一无条件释放一次
            //addListMapRefNum(expr);

            //每个表达式依次入栈
            callFunStack->push_back(expr.shallowMoveCopy());
        }

        objIndex = argVec.size();
    }


    //检查是否有默认参数需要添加。
    if (fun_info->paraList != nullptr && fun_info->paraList->back() == EXPR_INT_OPTION)
    {
        //可选参数时，paraList->size()总是比实际参数多1个，比如需要A B(B是可选），则此时paraList->size = 3
        //当调用函数只给一个参数A时，则stackSize=3;
        if (fun_info->paraList->size() == stackSize)
        {
            //如果最后一个是默认参数，而且当前调用真的没有给默认参数,则自动添加1个默认参数
            ExprValue defExpr;
            defExpr.type = EXPR_INT;
            defExpr.value.vint = fun_info->paraList->at(fun_info->paraList->size() - 2);

            //每个表达式依次入栈
            callFunStack->push_back(defExpr.shallowMoveCopy());
            objIndex++;

            stackSize++;
        }
        else if (fun_info->paraList->size() == (stackSize - 1))
        {
            //可给默认参数，但是调用时已经给了函数默认值，则必须是int类型，目前只支持int可选。
            int type = callFunStack->last()->type;
            if (type != EXPR_INT && type != EXPR_INT64)
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数类型和其定义无法匹配！").arg(curLine).arg(curStatement).arg(QStr(funName));
                AbortException(errmsg);
            }
        }
    }

    //把对象本身入栈
    //如果不是变量，而是全局方法 isKeyWordTypeVar
    if (!isBaoFunCall)
    {

        //上面已经获取过了
        //目前只有文件，日期，列表、字典四种局部内部函数的对象。结构体是没有的。
        //还是一个修改对象自身的问题，有些函数，比如QDatetime的setDate方式，是修改调用对象本身。此种情况下，如果是变量直接调用
        //使用上面getVarFromSymTable的方式，则没有问题。但是，如果是列表或字典中的文件，日期等对象，进一步调用函数呢？
        //前面ExprValue objExpr = std::any_cast<ExprValue>(visit(ctx->memberFunAccess()->funobj()->pinvar()));
        //获取的返回值 objExpr,对日期，字符串等都已经是深度拷贝的结构，文件本身是浅引用没有该问题。如果解决该问题呢？即pin语言没有
        //指针或引用，如果修改对象本身的值呢？使用返回值覆盖源对象，是个办法，但是不太优雅。综合考虑，针对pinvar的访问，提供了前面
        //的引用获取方式。见visitPinvar(ctx,true);

        callFunStack->push_back(objExpr.shallowMoveCopy());
        //可以看到，这里其实给的都是引用，所以直接修改对象会导致原值被修改。
        //故是可以在cpp中直接修改原值的。既然如此，对于列表、文件，都没有问题，因为使用可使用addListMapRefNum
        //但是对于字符串和日期这两种，其实是有问题的。因为日期和时间在底层修改后，后续删除参数的时候，这里没有
        //深拷贝，会导致原始变量被删除。所有干脆这里统一都不加计数。删除参数的时候也同样不删除该变量内容。

        //增加依次引用。20250214 对象本身都是引用传递到cpp函数中
        //addListMapRefNum(pSym);
    }
    else
    {
        //如果是全局方法，给出类名称
        //这里这个好像泄漏了，20250405
        ExprValue glboalExpr;
        glboalExpr.type = EXPR_GLOBAL_PACKNAME;
        //glboalExpr.setTypeName(*objExpr.varName);
        glboalExpr.value.vpacktype = objExpr.value.vpacktype;
        callFunStack->push_back(glboalExpr.shallowMoveCopy());

    }

    //函数名称
    ExprValue funNameExpr;
    funNameExpr.type = EXPR_STRING;
    funNameExpr.value.vpoint = new QByteArray(QByteArray::fromStdString(funName));
#ifdef PIN_MEM_REF
    newTime();
#endif
    callFunStack->push_back(funNameExpr.shallowMoveCopy());

    //先做参数检查,提取检查
    //一定先检查参数是否能够匹配，后续则放开去调用即可。
    checkCallFunPara(ctx, funName, *fun_info);

    //调用函数
    callFun(fun_info, ctx);

    //多级调用也是需要返回值的。
    bool getRetValue = (isSetFlag(flag, NEED_RETURN) || isSetFlag(flag, MULTI_CALL_FUN));

    //如果是最后一级多级调用，而外部不需要返回值，则也丢弃
    if (getRetValue && isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN) && isSetFlag(flag, NO_NEED_RETURN))
    {
        getRetValue = false;
    }

    //是否有返回值
    if (callFunStack->size() > stackSize)
    {
        //说明有返回值
        ExprValue* pRet = callFunStack->last();
#ifdef PIN_DEBUG
        std::cout << u8"函数返回值是" << pRet->toString().toStdString() << std::endl;
#endif

        if (!getRetValue)
        {
            //如果不要返回值，则啥也不干。后面结果也会被删除。
        }
        else
        {
            //要返回值。或者是链式调用的中间结果，不是最后一级,直接把结果返回到函数中去。
            if (ctxParent == nullptr || (isSetFlag(flag, MULTI_CALL_FUN) && !isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN)))
            {
                QList<ExprValue*>::iterator it = callFunStack->begin();
                it += stackSize;

                QList<SymNode*>* retList = new QList<SymNode*>();
#ifdef PIN_MEM_REF
                newTime();
#endif
                for (; it != callFunStack->end(); ++it)
                {
                    SymNode* pSym = new SymNode();
#ifdef PIN_MEM_REF
                    newTime();
#endif
                    pSym->type = (*it)->type;

                    FillSymNodeByExpr(pSym, *(*it), ctx);

                    retList->append(pSym);
                }

                //再直接把返回值写入到当前调用函数的返回值中。
                setcurFunReturnValue(retList);

            }
            else
            {
                //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。
                //如果不是多级调用，或者是最后一级多级调用。中间的链式调用的返回值不能给外部参数赋值，那是中间结果。

                PinParser::Fun_retContext* pFunRet = ctxParent->fun_ret();
                if (pFunRet != nullptr && (!isSetFlag(flag, MULTI_CALL_FUN) || isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN)))
                {

                    antlr4::tree::TerminalNode* pAutoDef = pFunRet->FUN_RET_AUTO_DEF();
                    if (pAutoDef == nullptr)
                    {
                        QList<ExprValue*>::iterator it = callFunStack->begin();
                        it += stackSize;


                        //如果不是自动定义。检查返回的参数值是否存在，不存在就抛出异常
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                        if (retIdVec.size() != (callFunStack->size() - stackSize))
                        {

                            QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(curLine).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(funName));
                            AbortException(errmsg);
                            return 0;
                        }

                        for (auto retId : retIdVec)
                        {
                            std::string varStr = retId->getText();

                            if (varStr != std::string("_"))
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                //这里千万不能要，这里不能是当前作用域。
                                //if (varName.size() > 0 && !isLoaclVarAlreadyExist(varName))
                                //{
                                //    //返回值不存在于作用域
                                //    QString errmsg = QString(u8"错误：行号 %1 语句 %2 变量 %3 参数未定义 ").arg(curLine).arg(curStatement)
                                //        .arg(QString::fromStdString(varStr));
                                //    AbortException(errmsg);
                                //    return 0;
                                //}

                                //赋值语句不要忘记。
                                 //创建返回参数变量
                                SymNode* pVar = getVarFromSymTable(varName,ctx);

                                FillSymNodeByExpr(pVar, *(*it),ctx);

                            }
                            ++it;
                        }
                    }
                    else
                    {
                        //如果是自动定义，则参数不能和已有冲突
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                        QList<ExprValue*>::iterator it = callFunStack->begin();
                        it += stackSize;

                        if (retIdVec.size() != (callFunStack->size() - stackSize))
                        {

                            QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(curLine).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(funName));
                            AbortException(errmsg);
                            return 0;
                        }
                        for (auto retId : retIdVec)
                        {
                            std::string varStr = retId->getText();

                            if (varStr != std::string("_"))
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                if (isLoaclVarAlreadyExist(varName))
                                {
                                    //返回值参数已经存在

                                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 变量 %3 已经在当前作用域中存在，不能重复使用 := 符号自动创建该变量 ").arg(curLine).arg(QString::fromStdString(ctxParent->getText())).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                                else
                                {
                                    /*
                                    int type = getVarTypeByName(varStr);
                                    //自动创建这部分变量，创建之前，先判断是否参数合法
                                    if (exprTypeMatch(type, (*it)->type, true) < 0)
                                    {

                                        QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 返回值 %4 和变量 %5 类型不匹配！").arg(curLine).arg(curStatement).arg(QStr(funName)).arg(getExpeTypeValue((*it)->type)).arg(QStr(varStr));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                    else*///不需要判断了，新版本的变量名称，不含有类型。
                                    {
                                        //创建返回参数变量
                                        SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
                                        newTime();
#endif
                                        newVar->name = varStr;
                                        newVar->type = (*it)->type;

                                        FillSymNodeByExpr(newVar, *(*it), ctx);
                                        //后续会直接使用名称访问这些变量。
                                        getPinSymTable()->append(newVar);
                                    }

                                }
                            }
                            ++it;

                        }
                    }

                }
            }
        }

    }
    else
    {
        //没有返回值，但是外部却在接收返回值，必须报错。
        if (getRetValue)
        {
            //是链式调用的中间
            if (isSetFlag(flag, MULTI_CALL_FUN) && !isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN))
            {
                QString msg = QString(u8"错误： 行 %1 语句 %2 函数 %3 没有返回值，无法继续后续的链式调用，请检查！").arg(curLine).arg(QStr(ctxParent->getText())).arg(QStr(funName));
                AbortException(msg);
            }

            if (ctxParent != nullptr)
            {
                //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。
                PinParser::Fun_retContext* pFunRet = ctxParent->fun_ret();
                if (pFunRet != nullptr)
                {
                    QString msg = QString(u8"错误： 行 %1 语句 %2 函数 %3 没有返回值，无法给变量 %4 进行赋值，请检查！").arg(curLine).arg(QStr(ctxParent->getText())).arg(QStr(funName)).arg(QStr(pFunRet->getText()));
                    AbortException(msg);
                }
            }

            if (isSetFlag(flag, NEED_RETURN))
            {
                QString msg = QString(u8"错误： 行 %1 语句 %2 函数 %3 没有返回值，而该调用函数却需要返回值，请检查！").arg(curLine).arg(curStatement).arg(QStr(funName));
                AbortException(msg);
        }
    }
    }

    //对象自身在位置 objIndex，这个位置不能调用freeMem，前文说过，对象是浅拷贝，不能删除，否则破坏变量自身值。
    //删除所有参数和返回值等。
    int i = 0;
    for (QList<ExprValue*>::iterator it = callFunStack->begin(); it != callFunStack->end(); ++it, ++i)
    {
        if (i != objIndex) //跳过对象变量自身的删除，因为对象变量参数本身是引用
        {
            (*it)->freeMem();
        }
        else
        {
            //消除引用计数
            //subListMapRefNum(*(*it)); //虽然对象不删除，但是要去掉一次引用。因为引用visitpinvar获取时，无条件加了一次引用，只对文件、列表、字典。
            freeRefObjMem(*it);

        }
        delete (*it);
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
    }
    callFunStack->clear();

    return 0;
}


//转调用cpp的底层函数
//PinParser::RealCallFunContext* multiFunOriginCtx 如果是多级函数调用，则指向原始的ctx
std::any ExprVisitor::visitCallQtFun(PinParser::RealCallFunContext* ctx, PinParser::WithRetCallFunContext* ctxParent, int flag)
{
#ifdef PIN_DEBUG
    std::cout << "----- 11 visitCallQtFun" << ctx->getText() << std::endl;
#endif

    ExprValue objExpr;

    std::string objName = ctx->memberFunAccess()->funobj()->getText();


    bool isBaoFunCall = (ctx->memberFunAccess()->funobj()->pinvar() == nullptr);// isKeyWordTypeVar(objName);

    //如果不是变量，而是全局方法 isKeyWordTypeVar
    if (!isBaoFunCall)
    {
        //这里是通过获取引用的方式获取变量的引用，特别注意，因为函数存在需要修改原值的行为。这个objExpr在这里不能进行任何释放行为。
        //一定不能忘记，这里的obj不能释放，再说一次。但是要释放此时，对于文件，列表，字符串，要消除引用计数。
        objExpr = std::any_cast<ExprValue>(visitPinvar(ctx->memberFunAccess()->funobj()->pinvar(), true));
    }
    else
    {
        objExpr.type = EXPR_GLOBAL_PACKNAME;
        objExpr.value.vpacktype = getVarTypeByName(objName);
    }
    objExpr.varName = &objName;

    std::string funName = ctx->memberFunAccess()->VARNAME()->getText();

    #ifdef PIN_DEBUG
    std::cout << u8"进入调用函数" << funName << std::endl;
    #endif

    PinParser::ArgumentListContext* pArglist = ctx->argumentList();

    return visitCallQtFun(ctx, ctxParent, objExpr, funName, pArglist, isBaoFunCall, flag);

    //把下面的函数内容，提取到visitCallQtFun中去，后面多级调用要复用逻辑。
#if 0
    //是个特例，不能使用更加全面的ctxParent，因为设计到报错时的行号错误信息精度问题。
    CPP_FUN_INFO* fun_info = findCppFun(objExpr.type, name, ctx);

    //有些方法需要底层获取变量本身。
    if (fun_info->need_var_name == 1)
    {
        objExpr.varName = &objName;
    }

    std::vector<int> *  pParaList = fun_info->paraList;
    PinParser::ArgumentListContext* pArglist = ctx->argumentList();

    //检查调用参数个数能否匹配
    if (pParaList == nullptr && pArglist == nullptr)
    {
        //没有参数，匹配。
    }
    else if (pParaList != nullptr && pArglist != nullptr)
    {
        std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

        //有可选参数时，必须是少于1个或2个的情况。
        if (pParaList->back() == EXPR_INT_OPTION)
        {
            int num = pParaList->size() - argVec.size();
            if (num == 1 || num == 2)
            {
                //ok。可选的int参数，没有给值。
            }
            else
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！函数%3 最多接收 %4 个参数！").arg(curLine).arg(curStatement).arg(QString::fromStdString(name)).arg(pParaList->size()-1);
                AbortException(errmsg);
            }
        }
        else if (pParaList->back() == EXPR_PARA_DYNANIC)
        {
            //是动态参数，只检查参数个数的范围是否满足。
            if (argVec.size() > pParaList->operator[](1) || argVec.size() < pParaList->operator[](0))
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！函数%3 可接收 %4-%5 个参数！").arg(curLine).arg(curStatement).arg(QString::fromStdString(name)).arg(pParaList->operator[](0)).arg(pParaList->operator[](1));
                AbortException(errmsg);
            }
        }
        else if (pParaList->size() != argVec.size())
        {

            QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数个数和其定义无法匹配！").arg(curLine).arg(curStatement).arg(QStr(name));
            AbortException(errmsg); 
        }
    }
    else
    {
        //一个有，另一个没有。
            if (pParaList != nullptr)
            {
                //如果调用函数没有给参数，而函数定义可以接受一个动态参数，则也是可以的。
                if(pParaList->back() == EXPR_INT_OPTION && (pArglist == nullptr || pArglist->argument().size() == 0))
                {
                    //ok
                }
                else if((pParaList->back() == EXPR_PARA_DYNANIC) && (pArglist == nullptr || pArglist->argument().size() == 0))
                {
                    //是动态参数，目前只有toHex一个函数。
                }
            }
            else
            {
                //其余都是非法情况了。
                int num = 0;
                if (pParaList == nullptr || pParaList->size() == 0)
                {
                    num = 0;
                }
                else
                {
                    if (pParaList->back() == EXPR_INT_OPTION)
                    {
                        num = pParaList->size() - 1;
                    }
                    else
                    {
                        num = pParaList->size();
                    }
                }

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数和其定义无法匹配！函数 %3 最多需要 %4个参数").arg(curLine).arg(curStatement).arg(QStr(name)).arg(num);
                AbortException(errmsg);

                return 0;
            }
    }

    QList<SymNode*> paraSymList;

    QList<ExprValue*>* callFunStack = getFunCallStack();

    int stackSize = 2; //对象和名称，多2个参数

    int objIndex = 0; //把对象在栈中的位置记住。

    //先把函数的参数求值一下，现在还是在调用者的栈上面，务必特别注意。
    if (pArglist != nullptr)
    {

        //如果有参数，进入求参数值，而且把结构入栈的情况
        std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

        stackSize += argVec.size();

        for (PinParser::ArgumentContext* arg : argVec)
        {
            //cpp qt 调用函数上，只能有变量做参数，不能有函数或回调函数做参数。

            if(arg->rightvar() == nullptr)
            {

                QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 不能使用函数或回调函数 %4做参数！").arg(curLine).arg(curStatement).arg(QStr(name)).arg(QStr(arg->getText()));
                AbortException(errmsg);
                break;
            }
            //进入表达式求值
            ExprValue expr = std::any_cast<ExprValue>(visit(arg->rightvar()));

            //这里不需要加入计数，因为expr中已经加1了，而且这里没有释放。后续只存在释放。
            //这里加入依次计数，因为函数调用完毕后，要统一无条件释放一次
            //addListMapRefNum(expr);

            //每个表达式依次入栈
            callFunStack->push_back(expr.shallowMoveCopy());
        }

        objIndex = argVec.size();
    }


    //检查是否有默认参数需要添加。
    if (fun_info->paraList != nullptr && fun_info->paraList->back() == EXPR_INT_OPTION )
    {
        //可选参数时，paraList->size()总是比实际参数多1个，比如需要A B(B是可选），则此时paraList->size = 3
        //当调用函数只给一个参数A时，则stackSize=3;
        if (fun_info->paraList->size() == stackSize)
        {
            //如果最后一个是默认参数，而且当前调用真的没有给默认参数,则自动添加1个默认参数
            ExprValue defExpr;
            defExpr.type = EXPR_INT;
            defExpr.value.vint = fun_info->paraList->at(fun_info->paraList->size() - 2);

            //每个表达式依次入栈
            callFunStack->push_back(defExpr.shallowMoveCopy());
            objIndex++;

            stackSize++;
        }
        else if (fun_info->paraList->size() == (stackSize - 1))
        {
            //可给默认参数，但是调用时已经给了函数默认值，则必须是int类型，目前只支持int可选。
            if (callFunStack->last()->type != EXPR_INT)
            {

                QString errmsg = QString(u8"错误：行 %1 语句 %2 调用函数 %3 的参数类型和其定义无法匹配！").arg(curLine).arg(curStatement).arg(QStr(name));
                AbortException(errmsg);
            }
        }
    }

        //把对象本身入栈
        //如果不是变量，而是全局方法 isKeyWordTypeVar
        if(!isBaoFunCall)
        {

            //上面已经获取过了
            //目前只有文件，日期，列表、字典四种局部内部函数的对象。结构体是没有的。
            //还是一个修改对象自身的问题，有些函数，比如QDatetime的setDate方式，是修改调用对象本身。此种情况下，如果是变量直接调用
            //使用上面getVarFromSymTable的方式，则没有问题。但是，如果是列表或字典中的文件，日期等对象，进一步调用函数呢？
            //前面ExprValue objExpr = std::any_cast<ExprValue>(visit(ctx->memberFunAccess()->funobj()->pinvar()));
            //获取的返回值 objExpr,对日期，字符串等都已经是深度拷贝的结构，文件本身是浅引用没有该问题。如果解决该问题呢？即pin语言没有
            //指针或引用，如果修改对象本身的值呢？使用返回值覆盖源对象，是个办法，但是不太优雅。综合考虑，针对pinvar的访问，提供了前面
            //的引用获取方式。见visitPinvar(ctx,true);

            callFunStack->push_back(objExpr.shallowMoveCopy());
            //可以看到，这里其实给的都是引用，所以直接修改对象会导致原值被修改。
            //故是可以在cpp中直接修改原值的。既然如此，对于列表、文件，都没有问题，因为使用可使用addListMapRefNum
            //但是对于字符串和日期这两种，其实是有问题的。因为日期和时间在底层修改后，后续删除参数的时候，这里没有
            //深拷贝，会导致原始变量被删除。所有干脆这里统一都不加计数。删除参数的时候也同样不删除该变量内容。

            //增加依次引用。20250214 对象本身都是引用传递到cpp函数中
            //addListMapRefNum(pSym);
        }
        else
        {
            //如果是全局方法，给出类名称
            ExprValue objExpr;
            objExpr.type = EXPR_TYPE_NAME;
            objExpr.setTypeName(objName);
            callFunStack->push_back(objExpr.shallowMoveCopy());

        }

        //函数名称
        ExprValue funNameExpr;
        funNameExpr.type = EXPR_STRING;
        funNameExpr.value.vpoint = new QByteArray(QByteArray::fromStdString(name));
#ifdef PIN_MEM_REF
        newTime();
#endif
        callFunStack->push_back(funNameExpr.shallowMoveCopy());

        //先做参数检查,提取检查
        //一定先检查参数是否能够匹配，后续则放开去调用即可。


        checkCallFunPara(ctx, name, *fun_info);

        //调用函数
        callFun(fun_info,ctx);

        //是否有返回值
        if(callFunStack->size() > stackSize)
        {
            //说明有返回值
            ExprValue* pRet = callFunStack->last();
#ifdef PIN_DEBUG
            std::cout << u8"函数返回值是" << pRet->toString().toStdString() << std::endl;
#endif
            if (!getRetValue)
            {
                //如果不要返回值，则啥也不干。后面结果也会被删除。
            }
            else
            {
                //要返回值
                if (ctxParent == nullptr)
                {
                    QList<ExprValue*>::iterator it = callFunStack->begin();
                    it += stackSize;

                    QList<SymNode*>* retList = new QList<SymNode*>();
#ifdef PIN_MEM_REF
                    newTime();
#endif
                    for (; it != callFunStack->end(); ++it)
                    {
                        SymNode* pSym = new SymNode();
#ifdef PIN_MEM_REF
                        newTime();
#endif
                        pSym->type = (*it)->type;

                        FillSymNodeByExpr(pSym, *(*it));

                        retList->append(pSym);
                    }

                    //再直接把返回值写入到当前调用函数的返回值中。
                    setcurFunReturnValue(retList);

                }
                else
                {
                    //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。
                    PinParser::Fun_retContext* pFunRet = ctxParent->fun_ret();
                    if (pFunRet != nullptr)
                    {

                        antlr4::tree::TerminalNode* pAutoDef = pFunRet->FUN_RET_AUTO_DEF();
                        if (pAutoDef == nullptr)
                        {
                            //如果不是自动定义。检查返回的参数值是否存在，不存在就抛出异常
                            std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                            for (auto retId : retIdVec)
                            {
                                std::string varStr = retId->getText();

                                if (varStr != "_")
                                {
                                    //检查参数是否存在。
                                    std::string varName = getPinvarName(retId->pinvar());

                                    if (varName.size() > 0 &&  !isLoaclVarAlreadyExist(varName))
                                    {
                                        //返回值不存在于作用域
                                        QString errmsg = QString(u8"错误：变量 %1 参数未定义 ").arg(QString::fromStdString(varStr));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                }

                            }
                        }
                        else
                        {
                            //如果是自动定义，则参数不能和已有冲突
                            std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                            QList<ExprValue*>::iterator it = callFunStack->begin();
                            it += stackSize;

                            if (retIdVec.size() != (callFunStack->size() - stackSize))
                            {

                                QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(curLine).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(name));
                                AbortException(errmsg);
                                return 0;
                            }
                            for (auto retId : retIdVec)
                            {
                                std::string varStr = retId->getText();

                                if (varStr != "_")
                                {
                                    //检查参数是否存在。
                                    std::string varName = getPinvarName(retId->pinvar());

                                    if (isLoaclVarAlreadyExist(varName))
                                    {
                                        //返回值参数已经存在

                                        QString errmsg = QString(u8"错误：函数 %1 语句 %2 变量 %3 已经在当前作用域中存在，不能重复使用 := 符号自动创建该变量 ").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctxParent->getText())).arg(QString::fromStdString(varStr));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                    else
                                    {
                                        int type = getVarTypeByName(varStr);
                                        //自动创建这部分变量，创建之前，先判断是否参数合法
                                        if (exprTypeMatch(type, (*it)->type, true) < 0)
                                        {

                                            QString errmsg = QString(u8"错误：行号 %1 语句 %2 函数 %3 返回值 %4 和变量 %5 类型不匹配！").arg(curLine).arg(curStatement).arg(QStr(name)).arg(getExpeTypeValue((*it)->type)).arg(QStr(varStr));
                                            AbortException(errmsg);
                                            return 0;
                                        }
                                        else
                                        {
                                            //创建返回参数变量
                                            SymNode* newVar = new SymNode();
                            #ifdef PIN_MEM_REF
                                newTime();
                            #endif
                                            newVar->name = varStr;
                                            newVar->type = type;

                                            FillSymNodeByExpr(newVar,*(*it));
                                            //后续会直接使用名称访问这些变量。
                                            getPinSymTable()->append(newVar);
                                        }

                                    }
                                }
                                ++it;

                            }
                        }

                    }
                }                 
            }

        }
        else
        {
            //没有返回值，但是外部却在接收返回值，必须报错。
            if (getRetValue)
            {
                if (ctxParent != nullptr)
                {
                    //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。
                    PinParser::Fun_retContext* pFunRet = ctxParent->fun_ret();
                    if (pFunRet != nullptr)
                    {

                        QString msg = QString(u8"错误： 行 %1 语句 %2 函数 %3 没有返回值，无法给变量 %4 进行赋值，请检查！").arg(curLine).arg(QStr(ctxParent->getText())).arg(QStr(name)).arg(QStr(pFunRet->getText()));
                        AbortException(msg);
                    }
                }
            }
        }

        //对象自身在位置 objIndex，这个位置不能调用freeMem，前文说过，对象是浅拷贝，不能删除，否则破坏变量自身值。
        //删除所有参数和返回值等。
        int i = 0;
        for(QList<ExprValue*>::iterator it = callFunStack->begin(); it != callFunStack->end(); ++it,++i)
        {
            if (i != objIndex) //跳过对象变量自身的删除，因为对象变量参数本身是引用
            {
                (*it)->freeMem();
            }
            else
            {
                //消除引用计数
                //subListMapRefNum(*(*it)); //虽然对象不删除，但是要去掉一次引用。因为引用visitpinvar获取时，无条件加了一次引用，只对文件、列表、字典。
                freeRefObjMem(*it);
            }
            delete (*it);
#ifdef PIN_MEM_REF
            freeTimes++;
#endif
        }
        callFunStack->clear();




  return 0;

#endif
}

// 替换字符串中的指定子字符串。只替换第一个
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length();
        return;
    }

}

//多级调用返回的对象，是否合法，能否继续进行多级调用
bool multiCallTempObjIsVaild(int type)
{
    switch(type)
    {

    case EXPR_STRING: 
    case EXPR_LIST:
    case EXPR_MAP:
    case EXPR_FILE:
    case EXPR_EXCEL:
    case EXPR_DATE:
    case EXPR_WCHAR:
    case EXPR_CHAR:
    case EXPR_U16STRING:
    case EXPR_STRUCT:
        return true;
    }
    return false;
}

//执行普通函数,即用户自己写的常规函数
std::any ExprVisitor::visitRealCallNormalFun(PinParser::RealCallFunContext* ctx, PinParser::WithRetCallFunContext* ctxParent, \
        std::string funName, PinParser::ArgumentListContext* pArglist, int flag)
{

    //多级调用也是需要返回值的。
    bool getRetValue = (isSetFlag(flag, NEED_RETURN) || isSetFlag(flag, MULTI_CALL_FUN));

    ////如果是最后一级多级调用，而外部不需要返回值，则也丢弃。普通函数不可能是最后一级调用
    //if (getRetValue && isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN) && isSetFlag(flag, NO_NEED_RETURN))
    //{
    //    getRetValue = false;
    //}

    if (!getRetValue)
    {
        std::string name = funName; //ctx->VARNAME()->getText();
        #ifdef PIN_DEBUG
        //std::cout << u8"进入调用函数" << name << std::endl;
        #endif

        //查找函数体
        FUN_SYM_INFO* pFunInfo = findFunBlock(name);
        if (pFunInfo == nullptr) {
            #ifdef PIN_DEBUG
            std::cout << u8"调用函数失败 函数名称 " << name << std::endl;
            #endif

            QString msg = QString(u8"错误：行号 %1 语句 %2 无法找到函数 %3 的定义, 变量%3 函数没有定义 ！是否把变量写错为函数调用？").arg(curLine).arg(curStatement).arg(QStr(name));
            AbortException(msg);
            return 0;
        }
        else
        {
            std::string* pBlock = pFunInfo->funBlock;
            std::vector<std::string>* pParaList = pFunInfo->paraList;
            //PinParser::ArgumentListContext* pArglist = ctx->argumentList();

            //检查调用参数个数能否匹配
            if (pParaList == nullptr && pArglist == nullptr)
            {
                //没有参数，匹配。
            }
            else if (pParaList != nullptr && pArglist != nullptr)
            {
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();
                int paraNum = pParaList->size() /2 ;

                if (paraNum != argVec.size())
                {
                    QString errmsg = QString(u8"行号 %1 语句 %2 函数 %3 调用的参数个数和函数定义无法匹配；%3 至多需要 %4 个参数，却给了%5个参数").arg(curLine).arg(QStr(ctx->getText())).arg(QStr(name)).arg(paraNum).arg(argVec.size());
                      AbortException(errmsg);
                }
                else
                {

                }
            }
            else
            {
                QString errmsg = QString(u8"调用函数 %1 的参数和其定义无法匹配！").arg(QString::fromStdString(name));
                AbortException(errmsg);

                return 0;
            }

            QList<SymNode*> paraSymList;

            //先把函数的参数求值一下，现在还是在调用者的栈上面，务必特别注意。
            if (pArglist != nullptr)
            {
                //如果有参数，进入求参数值，而且把结构入栈的情况
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

                //访问每个参数表达式
                //std::vector<std::string>::iterator it = pParaList->begin();
                int paraNum = pParaList->size() /2;

                for (int i =0, c = argVec.size(); i<c; ++i)
                {
                    PinParser::ArgumentContext* arg = argVec.at(i);

                    ExprValue expr;

                    int paraType = getVarTypeByName(pParaList->at(i+paraNum));
                    //如果参数是函数，则需要特别对待
                    if(paraType == EXPR_FUN)
                    {
                        //std::cout << "--1" << arg->rightvar()->getText() << std::endl;
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                        //必须要是函数，否则报错
                        if(expr.type != EXPR_FUN)
                        {
                            QString errmsg = QString(u8"行号 %1 语句 %2 调用函数 %3 第 %4 个参数 %5不是回调函数，和函数定义形式 %6 无法匹配！").arg(curLine).arg(curStatement)
                                        .arg(QStr(name)).arg(i+1).arg(QStr(argVec[i]->getText())).arg(QStr(pFunInfo->funDec));
                            AbortException(errmsg);
                        }

                        //已经是函数类型了，不需要做其它。
                        //全局函数做参数。
                        expr.type = EXPR_CALL_BACK_FUN; //表示为hd回调类型。
                        paraType = EXPR_CALL_BACK_FUN;
                        //expr.value.vpoint = new std::string(arg->rightvar()->getText());
                        //#ifdef PIN_MEM_REF
                        //            newTime();
                        //#endif
                    }

                    //进入表达式求值,非函数做参数的情况。
                    else if(arg->rightvar() != nullptr)
                    {
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                    }

                    //形参 和 表达式类型是否匹配
                    //int paraType = getVarTypeByName(pParaList->at(i+paraNum));

                    SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif

                    newVar->name = pParaList->at(i);
                    newVar->type = paraType;


                    //基本变量，结构体都是传值拷贝；列表和字典是传递引用
                    if (FillSymNodeByExpr(newVar, expr, ctx, true) >= 0)
                    {
                        //定义一个新的形参栈变量，把变量入栈
                        //定义变量
                        expr.freeMem();


                        //这里不能现在就入栈符号表。，要放入到后面根作用域之后。
                        paraSymList.append(newVar);
                        //加入到符号表中，延后加入。
                        //getPinSymTable()->append(newVar);

                    }
                    else
                    {
                        size_t offset = i + 1;

                        //参数和值不能匹配
                        QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用的参数 %3 类型无法匹配形参类型！函数 %4 第 %5 个参数申明需要 %6, 给定实参值却是 %7").arg(curLine).arg(curStatement).
                                arg(QString::fromStdString(arg->getText())).arg(QStr(name)).arg(offset).arg(getExpeTypeValue(paraType)).arg(getExpeTypeValue(expr.type));
                        AbortException(errmsg);
                        return 0;
                    }
                }
            }

            //从现在开始，这里就是进入新函数的作用域了。
            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //遇到调用函数，把函数名入栈
            SymNode* node = new SymNode();
            #ifdef PIN_MEM_REF
            newTime();
#endif
            node->name = name;
            node->type = FUN_SYM;

            //这里有问题，因为这个vint在后面其实已经被使用过了，是标识是否需要返回值。见NEED_FUN_RET_VALUE
            //所有这里不能复用。采样 line&funname的方式，加入到name中？
            //node->value.vint = ctx->getStart()->getLine();//把当前的行号记住一下。后续崩溃栈打印需要这个。
            //前面1个vint已经被NEED_FUN_RET_VALUE使用了，只能使用后面一个vint2。
            node->value.v2int.vint2 = ctx->getStart()->getLine();

            getPinSymTable()->push_back(node);

            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //再加入一个根作用域。保证后续参数的定义，是在该作用域之后。
            //第一个作用域中的参数定义，不能覆盖形参，这是一个规则。所以这里要无条件插入一个作用域，表示函数的根作用域。
            SymNode* nodeScope = new SymNode;
            #ifdef PIN_MEM_REF
                newTime();
            #endif
            nodeScope->type = SCOPE_SYM;
            //作用域反而是没有名称的。
            getPinSymTable()->push_back(nodeScope);

            //加入根作用域之后，再把参数入栈，顺序一定不能乱。保证形参是放在根作用域之后。
            for (auto v : paraSymList)
            {
                getPinSymTable()->push_back(v);
            }

            //表示刚刚函数的第一个块。后续进入块时，如果发现是根块， 不需要再加入作用域。
            pushStatus(INTO_FUN_FIRST_BLOCK_SCOPE);

            //执行函数体
            #ifdef PIN_DEBUG
            //std::cout << u8"将执行函数体代码" << *pBlock << std::endl;
            #endif

            /*
            antlr4::ANTLRInputStream bodyStream(*pBlock);

            PinLexer lexer(&bodyStream);

            CommonTokenStream tokens(&lexer);
            //tokens.fill();

 #ifdef PIN_DEBUG
            //// 打印 TokenStream 内容
            //std::cout << u8"调用函数的token如下" << std::endl;

            //    for (auto token : tokens.getTokens()) {
            //        std::cout << "Token: " << token->getText()
            //                  << ", Type: " << token->getType()
            //                  << ", Line: " << token->getLine() << std::endl;
            //    }
#endif
            PinParser parser(&tokens);
            PinErrListener errListener;
            errListener.tokens = &tokens;

            parser.removeErrorListeners();
            parser.addErrorListener(&errListener);

            tree::ParseTree* tree = parser.block();
            ExprVisitor expr;
            expr.visit(tree);
            */
            visitBlock(dynamic_cast<PinParser::BlockContext*>(pFunInfo->pBlock));


            //如果是通过fanhui 语句返回。
            if (getPinRunStatus() == FUNCTION_RET)
            {
                popStatus();

                //不需要返回值。则不应该返回值。应该是在外面就判定过。
                if (nullptr != node->funRetValue)
                {
                    //参数和值不能匹配。不算致命错误。打印而不异常终止。
                    QString errmsg = QString(u8"警告：函数 %1 调用时不需要返回值，实际有返回值！").arg(QString::fromStdString(name));
                    std::cout << errmsg.toStdString() << std::endl;


                    QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);

                    for (int i = 0, c = retList->size(); i < c; ++i)
                    {
                        retList->at(i)->destory();
                        delete retList->at(i);

#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                    }
                    delete retList;
                    node->funRetValue = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }


            }
            else
            {
                //自然返回，没有遇到fanhui语句。即不需要返回什么值。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                //如果函数定义有返回参数，则必须要通过fanhui返回；否则报错。
                //入口函数hs_rukou做个例外，没有返回值就没有，默认返回0
                if (pRetList != nullptr && name != "hs_rukou")
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"错误：行号%1 语句%2 %3 值没有返回值,该函数定义形式需要返回值 ！").arg(curLine).arg(curStatement).arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
            }

            //函数体在执行完毕的时候，不需要销毁形参，因为形参变量已经在函数根作用域之上，根作用域销毁时已经销毁了它们。
            //销毁函数要注意，因为可能存在返回值在函数的栈变量上。
            //destory_temp_para_ref(temp_para_ref);
            deleteCurFunction();

        }
    }
    else
    {
        //要函数返回结果的情况。
        std::string name = funName;//ctx->VARNAME()->getText();
        //std::cout << u8"进入调用函数" << name << std::endl;

        //查找函数体
        FUN_SYM_INFO* pFunInfo = findFunBlock(name);
        if (pFunInfo == nullptr) {
            std::cout << u8"调用函数失败 函数名称 " << name << std::endl;

            QString msg = QString(u8"错误：行号 %1 语句 %2 无法找到函数 %3 的定义, 变量%3 函数没有定义 ！是否把变量写错为函数调用？").arg(curLine).arg(curStatement).arg(QStr(name));
            AbortException(msg);
            return 0;
        }
        else
        {
            std::string* pBlock = pFunInfo->funBlock;
            std::vector<std::string>* pParaList = pFunInfo->paraList;
            //PinParser::ArgumentListContext* pArglist = ctx->argumentList();

            //检查调用参数个数能否匹配
            if (pParaList == nullptr && pArglist == nullptr)
            {
                //没有参数，匹配。
            }
            else if (pParaList != nullptr && pArglist != nullptr)
            {
                int paraNum = pParaList->size() / 2;

                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();
                if (paraNum != argVec.size())
                {
                    QString errmsg = QString(u8"行号 %1 语句 %2 函数 %3 调用的参数个数和函数定义无法匹配；%3 至多需要 %4 个参数，却给了%5个参数").arg(curLine).arg(QStr(ctx->getText())).arg(QStr(name)).arg(paraNum).arg(argVec.size());
                    AbortException(errmsg);
                }
                else
                {

                }
            }
            else
            {
                QString errmsg = QString(u8"调用函数 %1 的参数和其定义无法匹配！").arg(QString::fromStdString(name));
                AbortException(errmsg);

                return 0;
            }

            QList<SymNode*> paraSymList;

            //先把函数的参数求值一下，现在还是在调用者的栈上面，前面注意。
            if (pArglist != nullptr)
            {
                //如果有参数，进入求参数值，而且把结构入栈的情况
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

                //访问每个参数表达式
                //std::vector<std::string>::iterator it = pParaList->begin();
                int paraNum = pParaList->size() / 2;

                for (int i =0, c = argVec.size(); i<c; ++i)
                {
                    PinParser::ArgumentContext* arg = argVec.at(i);
                    //进入表达式求值
                    ExprValue expr;

                    int paraType = getVarTypeByName(pParaList->at(i+paraNum));
                   //如果参数是函数，则需要特别对待
                   if(paraType == EXPR_FUN)
                   {
                       std::cout << "--1" << arg->rightvar()->getText() << std::endl;
                       expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                       //必须要是函数，否则报错
                       if(expr.type != EXPR_FUN)
                       {
                           QString errmsg = QString(u8"行号 %1 语句 %2 调用函数 %3 第 %4 个参数 %5不是回调函数，和函数定义形式 %6 无法匹配！").arg(curLine).arg(curStatement)
                                       .arg(QStr(name)).arg(i+1).arg(QStr(argVec[i]->getText())).arg(QStr(pFunInfo->funDec));
                           AbortException(errmsg);
                       }

                       //已经是函数类型了，不需要做其它。
                       //全局函数做参数。
                       expr.type = EXPR_CALL_BACK_FUN; //表示为hd回调类型。
                       paraType = EXPR_CALL_BACK_FUN;
                       //expr.value.vpoint = new std::string(arg->rightvar()->getText());
                       //#ifdef PIN_MEM_REF
                       //            newTime();
                       //#endif
                   }

                    //进入表达式求值
                    else if(arg->rightvar() != nullptr)
                    {
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                    }
                   /* else if(arg->CUSTOM_FUN_NAME())
                    {
                        expr.type = EXPR_FUN;
                        expr.value.vpoint = new std::string(arg->CUSTOM_FUN_NAME()->getText());
#ifdef PIN_MEM_REF
            newTime();
#endif
                    }
                    else if (arg->CALL_FUN())
                    {
                        //回调函数本身，二次在一个函数中做参数。需要获取回调函数本身指向的全局函数。
                        std::string hdName = arg->CALL_FUN()->getText();
                        SymNode* pHdSym = getVarFromSymTable(hdName);

                        expr.type = EXPR_FUN;
                        expr.value.vpoint = new std::string(*(std::string*)pHdSym->value.vpoint);
#ifdef PIN_MEM_REF
                        newTime();
#endif
                    }*/

                    //形参 和 表达式类型是否匹配
                    //int paraType = getVarTypeByName(pParaList->at(i+paraNum));

                    SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif

                    //如果是结构体，不需要结构体类名，只需要对象名称
                    //if(paraType != EXPR_STRUCT)
                    //{
                        newVar->name = pParaList->at(i);
                    /*}
                    else
                    {
                        //st.varname,只需要后面的varname即可
                        size_t pos = (*it).find(".");

                        newVar->name = (*it).substr(pos+1);
                    }
                    */
                    newVar->type = paraType;

                    if (FillSymNodeByExpr(newVar, expr, ctx, true) >= 0)
                    {
                        //定义一个新的形参栈变量，把变量入栈
                        //定义变量
                        expr.freeMem();

                        //这里不能入栈，要放入到后面根作用域之后。
                        paraSymList.append(newVar);
                        //加入到符号表中
                        //getPinSymTable()->append(newVar);
                    }
                    else
                    {
                        //参数和值不能匹配
                        QString errmsg = QString(u8"函数 %1 调用的第 %2 个参数 %3 类型无法匹配参数值！").arg(QString::fromStdString(name)).arg(QStr(pParaList->at(i))).arg(QString::fromStdString(arg->rightvar()->getText()));
                        AbortException(errmsg);
                        return 0;
                    }
                    //++it;

                }
            }


            //从现在开始，这里就是进入新函数的作用域了。
            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //遇到调用函数，把函数名入栈
            SymNode* node = new SymNode();
            #ifdef PIN_MEM_REF
            newTime();
#endif
            node->name = name;
            node->type = FUN_SYM;
            node->value.v2int.vint2 = ctx->getStart()->getLine();


            bool isFunNeedReturnValue = false;

            PinParser::Fun_retContext* pFunRet = nullptr;
            //这里记录一下，如果函数需要关注返回值，则设置
            //判断函数调用者，是否需要关注返回值。即调用函数有接受参数，或者显示返回需要返回值。

            //要结果，但是又没有fun_ret,直接return hs_xxx的方式。
            //20250214 加了一种模式：就是把函数返回值做表达式的情况。也走这里，类似于隐藏调用 return fun的方式。逻辑一样。
            //如果是链式调用，也要走这里。
            if (ctxParent == nullptr || isSetFlag(flag, MULTI_CALL_FUN))
            {
                //直接给出返回值，但是不赋值给外面的变量即可。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                if (pRetList == nullptr)
                {
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用函数 %3 没有返回值，不能接收该函数返回值 ！").arg(curLine).arg(curStatement).arg(QStr(name));
                    AbortException(errmsg);
                    return 0;
                }

                //需要关注函数的返回值。
                node->value.vint = NEED_FUN_RET_VALUE;
                isFunNeedReturnValue = true;

                //这里还是有点问题。需要把函数的值?
            }
            else
            {
                //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。
                //如果不是多级调用，或者是最后一级多级调用才行(普通函数不可能是最后一级）。中间的链式调用的返回值不能给外部参数赋值，那是中间结果。


                pFunRet = ctxParent->fun_ret();
                if (pFunRet != nullptr && !isSetFlag(flag, MULTI_CALL_FUN))
                {
                    std::vector<std::string>* pRetList = pFunInfo->retList;
                    if (pRetList == nullptr)
                    {
                        QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用函数 %3 没有返回值，不能接收该函数返回值 ！").arg(curLine).arg(QStr(ctxParent->getText())).arg(QStr(name));
                        AbortException(errmsg);
                        return 0;
                    }

                    //需要关注函数的返回值。
                    node->value.vint = NEED_FUN_RET_VALUE;
                    isFunNeedReturnValue = true;

                    antlr4::tree::TerminalNode* pAutoDef = pFunRet->FUN_RET_AUTO_DEF();
                    if (pAutoDef == nullptr)
                    {
                        //如果不是自动定义。检查返回的参数值是否存在，不存在就抛出异常
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                        for (auto retId : retIdVec)
                        {
                            std::string varStr = retId->getText();

                            if (varStr != "_")
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                if (varName.size() > 0 &&  !isLoaclVarAlreadyExist(varName))
                                {
                                    //返回值不存在于作用域52
                                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 变量 %3 参数未定义 ").arg(curLine).arg(curStatement).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                            }

                        }
                    }
                    else
                    {
                        //如果是自动定义，则参数不能和已有冲突
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                        std::vector<std::string>* pRetList = pFunInfo->retList;

                        std::vector<std::string>::iterator it = pRetList->begin();

                        if (retIdVec.size() != pRetList->size())
                        {
                            QString errmsg = QString(u8"错误：函数中 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(name));
                            AbortException(errmsg);
                            return 0;
                        }

                        for (auto retId : retIdVec)
                        {
                            //PinParser::Ret_idContext* retId = retIdVec.at(i);

                            std::string varStr = retId->getText();

                            if (varStr != std::string("_"))
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                if (isLoaclVarAlreadyExist(varName))
                                {
                                    //返回值参数已经存在

                                    QString errmsg = QString(u8"错误：函数 %1 语句 %2 变量 %3 已经在当前作用域中存在，不能重复使用 := 符号自动创建该变量 ").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctxParent->getText())).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                                else
                                {
                                    /*int type = getVarTypeByName(varStr);
                                    //自动创建这部分变量，创建之前，先判断是否参数合法
                                    if (exprTypeMatch(type, getVarTypeByName(*it), true) < 0)
                                    {
                                        QString errmsg = QString(u8"错误：返回参数 %1 和函数定义形参 %2 类型不匹配！").arg(QString::fromStdString(*it)).arg(QString::fromStdString(varStr));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                    else*/
                                    {
                                        //创建返回参数变量
                                        SymNode* newVar = new SymNode();
                        #ifdef PIN_MEM_REF
                            newTime();
                        #endif
                                        newVar->name = varStr;
                                        newVar->type = getVarTypeByName(*it);
                                        //后续会直接使用名称访问这些变量。
                                        getPinSymTable()->append(newVar);
                                    }

                                }
                            }
                            ++it;

                        }
                    }

                }
            }

            getPinSymTable()->push_back(node);

            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //再加入一个根作用域。保证后续参数的定义，是在该作用域之后。
            //第一个作用域中的参数定义，不能覆盖形参，这是一个规则。所以这里要无条件插入一个作用域，表示函数的根作用域。
            SymNode* nodeScope = new SymNode;
            #ifdef PIN_MEM_REF
            newTime();
#endif
            nodeScope->type = SCOPE_SYM;
            //作用域反而是没有名称的。
            getPinSymTable()->push_back(nodeScope);

            //加入根作用域之后，再把参数入栈，顺序一定不能乱。保证形参是放在更作用域之后。
            for (auto v : paraSymList)
            {
                getPinSymTable()->push_back(v);
            }

            //表示刚刚函数的第一个块。后续进入块时，如果发现是根块， 不需要再加入作用域。
            pushStatus(INTO_FUN_FIRST_BLOCK_SCOPE);

            //执行函数体
            #ifdef PIN_DEBUG
            //std::cout << u8"将执行函数体代码" << *pBlock << std::endl;
            #endif

            /*
            antlr4::ANTLRInputStream bodyStream(*pBlock);

            PinLexer lexer(&bodyStream);

            CommonTokenStream tokens(&lexer);

            PinParser parser(&tokens);
            PinErrListener errListener;
            errListener.tokens = &tokens;

            parser.removeErrorListeners();
            parser.addErrorListener(&errListener);

            tree::ParseTree* tree = parser.block();
            ExprVisitor expr;
            expr.visit(tree);
            */
            visitBlock(dynamic_cast<PinParser::BlockContext*>(pFunInfo->pBlock));

            //函数体在执行完毕的时候，不需要销毁形参，因为形参变量已经在函数根作用域之上，根作用域销毁时已经销毁了它们。
            //销毁函数要注意，因为可能存在返回值在函数的栈变量上。

            //如果是通过fanhui 语句返回。
            if (getPinRunStatus() == FUNCTION_RET)
            {
                popStatus();

                //返回值在函数的作用域的valut.vpoint上面。
                if (isFunNeedReturnValue)
                {
                    //调用函数时，需要函数返回值
                    if (nullptr == node->funRetValue)
                    {
                        //看起来这下面的代码，应该是永远不走。
                        if (ctxParent != nullptr)
                        {
                        QString errmsg = QString(u8"错误：函数 %1 调用时缺少返回值，运行异常，请检查！").arg(QString::fromStdString(name));
                        AbortException(errmsg);
                        return 0;
                        }
                        else
                        {
                            //就是没有显示返回值的情况，无法把返回值写入参数变量
                            //先把返回值取出来。
                            QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                            node->funRetValue = nullptr;

                            //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                            deleteCurFunction();

                            //再直接把返回值写入到上层函数的返回值中。
                            setcurFunReturnValue(retList);

                            //务必返回，不能重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                    }
                    else
                    {
                        //有返回值的情况。检查返回值是否和调用者的变量匹配。

                        //是return hs_x 直接函数返回的情况，没有显示接收函数返回参数。
                        if (ctxParent == nullptr)
                        {

                            //就是没有显示返回值的情况，无法把返回值写入参数变量
                            //先把返回值取出来。
                            QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                            node->funRetValue = nullptr;

                            //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                            deleteCurFunction();

                            //在直接把返回值写入到上层函数的返回值中
                            setcurFunReturnValue(retList);

                            //务必返回，不能重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                        //先把返回值取出来。
                        QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                        node->funRetValue = nullptr;

                        //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                        deleteCurFunction();

                        //获取函数的返回值pFunRet
                        if (pFunRet == nullptr)
                        {
                            QString errmsg = QString(u8"错误：函数 %1 没有返回值，无法支持 fanhui %1 函数语句！").arg(QString::fromStdString(name));
                            AbortException(errmsg);
                            return 0;
                        }
                        else
                        {
                            //把函数返回值赋值。

                            std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                            QList<SymNode*>::iterator it = retList->begin();


                            for (auto retId : retIdVec)
                            {
                                std::string varStr = retId->getText();

                                if (varStr != std::string("_"))
                                {
                                    //注意这里*it反正后续要释放，这里掏空没有问题。
                                    ExprValue expr;
                                    expr.type = (*it)->type;
                                    expr.value.vpoint = (*it)->value.vpoint;
                                    (*it)->value.vint64 = 0;

                                    visitPinvar(retId->pinvar(),false, &expr);
                                    /*
                                    std::vector<PinParser::ListindexContext *> plistMap = retId->pinvar()->listindex();
                                    PinParser::StMemVarContext* pStructMem = retId->pinvar()->stMemVar();
                                    std::string varName = retId->pinvar()->VARNAME()->getText();

                                    SymNode* varNode = getVarFromSymTable(varName, ctx);

                                    if(plistMap.size() == 0 && pStructMem != nullptr)
                                    {
                                        assignStructMem(varNode, pStructMem, *it, ctxParent);

                                    }
                                    else if(retId->pinvar()->accesslist() != nullptr)
                                    {
                                        assignList(retId->pinvar()->accesslist(), *it, ctxParent);
                                    }
                                    else if(retId->pinvar()->accessmap() != nullptr)
                                    {
                                        assignMap(retId->pinvar()->accessmap(), *it, ctxParent);
                                    }
                                    //其余的直接按基本变量走
                                    else
                                    {
                                        SymNode* varNode = getVarFromSymTable(varStr, ctx);
                                        if (varNode != nullptr)
                                        {
                                            if (FillSymNodeBySymNode(varNode, *it) < 0)
                                            {
                                                QString errmsg = QString(u8"错误：变量 %1 不能使用 变量 %2 赋值，类型不匹配！").arg(QString::fromStdString(varNode->name)).arg(QString::fromStdString((*it)->name));
                                                AbortException(errmsg);
                                                return 0;
                                            }
                                        }
                                        else
                                        {
                                            QString errmsg = QString(u8"错误：找不到变量 %1，变量没有定义或书写错误，请检查 ！").arg(QString::fromStdString(varStr));
                                            AbortException(errmsg);
                                            return 0;
                                        }
                                    }
                                    */
                                }
                                //销毁返回值
                                (*it)->destory();
                                delete (*it);

#ifdef PIN_MEM_REF
                                freeTimes++;
#endif

                                ++it;
                            }

                            delete retList;
#ifdef PIN_MEM_REF
                            freeTimes++;
#endif

                            //务必返回，不能再重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                    }
                }
                else
                {
                    //不需要返回值。则不应该返回值。
                    if (nullptr != node->funRetValue)
                    {
                        //参数和值不能匹配。不算致命错误。打印而不异常终止。
                        QString errmsg = QString(u8"警告：函数 %1 调用时不需要返回值，实际也有返回值！").arg(QString::fromStdString(name));
                        std::cout << errmsg.toStdString() << std::endl;


                        QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);

                        for (int i = 0, c = retList->size(); i < c; ++i)
                        {
                            retList->at(i)->destory();
                            delete retList->at(i);

#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                        }
                        delete retList;
                        node->funRetValue = nullptr;
#ifdef PIN_MEM_REF
                        freeTimes++;
#endif
                    }

                }
            }
            else
            {
                //自然返回，没有遇到fanhui语句。即不需要返回什么值。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                //如果函数有返回参数，则必须要通过fanhui返回。
                if (pRetList != nullptr && name != "hs_rukou")
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"错误：行号 %1 函数 %2 体没有返回值,该函数形式需要返回值 ！").arg(curLine).arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
            }
            //destory_temp_para_ref(temp_para_ref);
            deleteCurFunction();

        }
    }

    return 0;
}

//执行普通函数,即用户自己写的常规函数
std::any ExprVisitor::visitRealCallNormalFun(PinParser::RealCallFunContext* ctx, PinParser::WithRetCallFunContext* ctxParent, int flag)
{
    //多级调用也是需要返回值的。
    bool getRetValue = (isSetFlag(flag, NEED_RETURN) || isSetFlag(flag, MULTI_CALL_FUN));

    ////如果是最后一级多级调用，而外部不需要返回值，则也丢弃。普通函数不可能是最后一级调用
    //if (getRetValue && isSetFlag(flag, MULTI_CALL_LAST_CALL_FUN) && isSetFlag(flag, NO_NEED_RETURN))
    //{
    //    getRetValue = false;
    //}
    //不要结果
    if (!getRetValue)
    {
        std::string name = ctx->VARNAME()->getText();
        #ifdef PIN_DEBUG
        //std::cout << u8"进入调用函数" << name << std::endl;
        #endif

        return visitRealCallNormalFun(ctx,ctxParent,name,ctx->argumentList(), flag);

#if 0
        //查找函数体
        FUN_SYM_INFO* pFunInfo = findFunBlock(name);
        if (pFunInfo == nullptr) {
            #ifdef PIN_DEBUG
            std::cout << u8"调用函数失败 函数名称 " << name << std::endl;
            #endif

            QString errmsg = QString(u8"无法找到函数 %1 的定义！").arg(QString::fromStdString(name));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);
            return 0;
        }
        else
        {
            std::string* pBlock = pFunInfo->funBlock;
            std::vector<std::string>* pParaList = pFunInfo->paraList;
            PinParser::ArgumentListContext* pArglist = ctx->argumentList();

            //检查调用参数个数能否匹配
            if (pParaList == nullptr && pArglist == nullptr)
            {
                //没有参数，匹配。
            }
            else if (pParaList != nullptr && pArglist != nullptr)
            {
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();
                int paraNum = pParaList->size() /2 ;

                if (paraNum != argVec.size())
                {
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用的参数和函数定义无法匹配！").arg(curLine).arg(QString::fromStdString(ctx->getText()));
                    AbortException(errmsg);
                }
                else
                {

                }
            }
            else
            {
                QString errmsg = QString(u8"调用函数 %1 的参数和其定义无法匹配！").arg(QString::fromStdString(name));
                AbortException(errmsg);

                return 0;
            }

            QList<SymNode*> paraSymList;

            //先把函数的参数求值一下，现在还是在调用者的栈上面，务必特别注意。
            if (pArglist != nullptr)
            {
                //如果有参数，进入求参数值，而且把结构入栈的情况
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

                //访问每个参数表达式
                //std::vector<std::string>::iterator it = pParaList->begin();
                int paraNum = pParaList->size() /2;

                for (int i =0, c = argVec.size(); i<c; ++i)
                {
                    PinParser::ArgumentContext* arg = argVec.at(i);

                    ExprValue expr;

                    int paraType = getVarTypeByName(pParaList->at(i+paraNum));
                    //如果参数是函数，则需要特别对待
                    if(paraType == EXPR_FUN)
                    {
                        std::cout << "--1" << arg->rightvar()->getText() << std::endl;
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                        //必须要是函数，否则报错
                        if(expr.type != EXPR_FUN)
                        {
                            QString errmsg = QString(u8"行号 %1 语句 %2 调用函数 %3 第 %4 个参数 %5不是回调函数，和函数定义形式 %6 无法匹配！").arg(curLine).arg(curStatement)
                                        .arg(QStr(name)).arg(i+1).arg(QStr(argVec[i]->getText())).arg(QStr(pFunInfo->funDec));
                            AbortException(errmsg);
                        }

                        //已经是函数类型了，不需要做其它。
                        //全局函数做参数。
                        expr.type = EXPR_CALL_BACK_FUN; //表示为hd回调类型。
                        paraType = EXPR_CALL_BACK_FUN;
                        //expr.value.vpoint = new std::string(arg->rightvar()->getText());
                        //#ifdef PIN_MEM_REF
                        //            newTime();
                        //#endif
                    }

                    //进入表达式求值,非函数做参数的情况。
                    else if(arg->rightvar() != nullptr)
                    {
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));


                    }

                    //形参 和 表达式类型是否匹配
                    //int paraType = getVarTypeByName(pParaList->at(i+paraNum));

                    SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif

                    newVar->name = pParaList->at(i);
                    newVar->type = paraType;


                    //基本变量，结构体都是传值拷贝；列表和字典是传递引用
                    if (FillSymNodeByExpr(newVar, expr, true) >= 0)
                    {
                        //定义一个新的形参栈变量，把变量入栈
                        //定义变量
                        expr.freeMem();


                        //这里不能现在就入栈符号表。，要放入到后面根作用域之后。
                        paraSymList.append(newVar);
                        //加入到符号表中，延后加入。
                        //getPinSymTable()->append(newVar);

                    }
                    else
                    {
                        size_t offset = i + 1;

                        //参数和值不能匹配
                        QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用的参数 %3 类型无法匹配形参类型！函数 %4 第 %5 个参数申明需要 %6").arg(curLine).arg(curStatement).arg(QString::fromStdString(arg->getText())).arg(QStr(name)).arg(offset).arg(getExpeTypeValue(paraType));
                        AbortException(errmsg);
                        return 0;
                    }
                }
            }

            //从现在开始，这里就是进入新函数的作用域了。
            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //遇到调用函数，把函数名入栈
            SymNode* node = new SymNode();
            #ifdef PIN_MEM_REF
            newTime();
#endif
            node->name = name;
            node->type = FUN_SYM;

            //这里有问题，因为这个vint在后面其实已经被使用过了，是标识是否需要返回值。见NEED_FUN_RET_VALUE
            //所有这里不能复用。采样 line&funname的方式，加入到name中？
            //node->value.vint = ctx->getStart()->getLine();//把当前的行号记住一下。后续崩溃栈打印需要这个。
            //前面1个vint已经被NEED_FUN_RET_VALUE使用了，只能使用后面一个vint2。
            node->value.v2int.vint2 = ctx->getStart()->getLine();

            getPinSymTable()->push_back(node);

            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //再加入一个根作用域。保证后续参数的定义，是在该作用域之后。
            //第一个作用域中的参数定义，不能覆盖形参，这是一个规则。所以这里要无条件插入一个作用域，表示函数的根作用域。
            SymNode* nodeScope = new SymNode;
            #ifdef PIN_MEM_REF
            newTime();
#endif
            nodeScope->type = SCOPE_SYM;
            //作用域反而是没有名称的。
            getPinSymTable()->push_back(nodeScope);

            //加入根作用域之后，再把参数入栈，顺序一定不能乱。保证形参是放在根作用域之后。
            for (auto v : paraSymList)
            {
                getPinSymTable()->push_back(v);
            }

            //表示刚刚函数的第一个块。后续进入块时，如果发现是根块， 不需要再加入作用域。
            pushStatus(INTO_FUN_FIRST_BLOCK_SCOPE);

            //执行函数体
            #ifdef PIN_DEBUG
            //std::cout << u8"将执行函数体代码" << *pBlock << std::endl;
            #endif

            antlr4::ANTLRInputStream bodyStream(*pBlock);

            PinLexer lexer(&bodyStream);

            CommonTokenStream tokens(&lexer);
            //tokens.fill();

 #ifdef PIN_DEBUG
            //// 打印 TokenStream 内容
            //std::cout << u8"调用函数的token如下" << std::endl;

            //    for (auto token : tokens.getTokens()) {
            //        std::cout << "Token: " << token->getText()
            //                  << ", Type: " << token->getType()
            //                  << ", Line: " << token->getLine() << std::endl;
            //    }
#endif
            PinParser parser(&tokens);
            PinErrListener errListener;
            errListener.tokens = &tokens;

            parser.removeErrorListeners();
            parser.addErrorListener(&errListener);

            tree::ParseTree* tree = parser.block();
            ExprVisitor expr;
            expr.visit(tree);

            //如果是通过fanhui 语句返回。
            if (getPinRunStatus() == FUNCTION_RET)
            {
                popStatus();

                //不需要返回值。则不应该返回值。应该是在外面就判定过。
                if (nullptr != node->funRetValue)
                {
                    //参数和值不能匹配。不算致命错误。打印而不异常终止。
                    QString errmsg = QString(u8"警告：函数 %1 调用时不需要返回值，实际有返回值！").arg(QString::fromStdString(name));
                    std::cout << errmsg.toStdString() << std::endl;


                    QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);

                    for (int i = 0, c = retList->size(); i < c; ++i)
                    {
                        retList->at(i)->destory();
                        delete retList->at(i);

#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                    }
                    delete retList;
                    node->funRetValue = nullptr;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }


            }
            else
            {
                //自然返回，没有遇到fanhui语句。即不需要返回什么值。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                //如果函数定义有返回参数，则必须要通过fanhui返回；否则报错。
                if (pRetList != nullptr)
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"错误：函数 %1 体没有返回值,该函数形式需要返回值 ！").arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
            }

            //函数体在执行完毕的时候，不需要销毁形参，因为形参变量已经在函数根作用域之上，根作用域销毁时已经销毁了它们。
            //销毁函数要注意，因为可能存在返回值在函数的栈变量上。
            //destory_temp_para_ref(temp_para_ref);
            deleteCurFunction();

        }
#endif


    }
    else
    {
        //要函数返回结果的情况。
        std::string name = ctx->VARNAME()->getText();
        //std::cout << u8"进入调用函数" << name << std::endl;
        return visitRealCallNormalFun(ctx,ctxParent,name,ctx->argumentList(), flag);
#if 0
        //查找函数体
        FUN_SYM_INFO* pFunInfo = findFunBlock(name);
        if (pFunInfo == nullptr) {
            std::cout << u8"调用函数失败 函数名称 " << name << std::endl;

            QString errmsg = QString(u8"无法找到函数 %1 的定义！").arg(QString::fromStdString(name));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);
            return 0;
        }
        else
        {
            std::string* pBlock = pFunInfo->funBlock;
            std::vector<std::string>* pParaList = pFunInfo->paraList;
            PinParser::ArgumentListContext* pArglist = ctx->argumentList();

            //检查调用参数个数能否匹配
            if (pParaList == nullptr && pArglist == nullptr)
            {
                //没有参数，匹配。
            }
            else if (pParaList != nullptr && pArglist != nullptr)
            {
                int paraNum = pParaList->size() / 2;

                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();
                if (paraNum != argVec.size())
                {
                    QString errmsg = QString(u8"行号 %1 语句 %2 调用的参数和函数定义无法匹配！").arg(curLine).arg(QStr(ctx->getText()));
                    AbortException(errmsg);
                }
                else
                {

                }
            }
            else
            {
                QString errmsg = QString(u8"调用函数 %1 的参数和其定义无法匹配！").arg(QString::fromStdString(name));
                AbortException(errmsg);

                return 0;
            }

            QList<SymNode*> paraSymList;

            //先把函数的参数求值一下，现在还是在调用者的栈上面，前面注意。
            if (pArglist != nullptr)
            {
                //如果有参数，进入求参数值，而且把结构入栈的情况
                std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

                //访问每个参数表达式
                //std::vector<std::string>::iterator it = pParaList->begin();
                int paraNum = pParaList->size() / 2;

                for (int i =0, c = argVec.size(); i<c; ++i)
                {
                    PinParser::ArgumentContext* arg = argVec.at(i);
                    //进入表达式求值
                    ExprValue expr;

                    int paraType = getVarTypeByName(pParaList->at(i+paraNum));
                   //如果参数是函数，则需要特别对待
                   if(paraType == EXPR_FUN)
                   {
                       std::cout << "--1" << arg->rightvar()->getText() << std::endl;
                       expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                       //必须要是函数，否则报错
                       if(expr.type != EXPR_FUN)
                       {
                           QString errmsg = QString(u8"行号 %1 语句 %2 调用函数 %3 第 %4 个参数 %5不是回调函数，和函数定义形式 %6 无法匹配！").arg(curLine).arg(curStatement)
                                       .arg(QStr(name)).arg(i+1).arg(QStr(argVec[i]->getText())).arg(QStr(pFunInfo->funDec));
                           AbortException(errmsg);
                       }

                       //已经是函数类型了，不需要做其它。
                       //全局函数做参数。
                       expr.type = EXPR_CALL_BACK_FUN; //表示为hd回调类型。
                       paraType = EXPR_CALL_BACK_FUN;
                       //expr.value.vpoint = new std::string(arg->rightvar()->getText());
                       //#ifdef PIN_MEM_REF
                       //            newTime();
                       //#endif
                   }

                    //进入表达式求值
                    else if(arg->rightvar() != nullptr)
                    {
                        expr = std::any_cast<ExprValue>(visit(arg->rightvar()));
                    }
                   /* else if(arg->CUSTOM_FUN_NAME())
                    {
                        expr.type = EXPR_FUN;
                        expr.value.vpoint = new std::string(arg->CUSTOM_FUN_NAME()->getText());
#ifdef PIN_MEM_REF
            newTime();
#endif
                    }
                    else if (arg->CALL_FUN())
                    {
                        //回调函数本身，二次在一个函数中做参数。需要获取回调函数本身指向的全局函数。
                        std::string hdName = arg->CALL_FUN()->getText();
                        SymNode* pHdSym = getVarFromSymTable(hdName);

                        expr.type = EXPR_FUN;
                        expr.value.vpoint = new std::string(*(std::string*)pHdSym->value.vpoint);
#ifdef PIN_MEM_REF
                        newTime();
#endif
                    }*/

                    //形参 和 表达式类型是否匹配
                    //int paraType = getVarTypeByName(pParaList->at(i+paraNum));

                    SymNode* newVar = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif

                    //如果是结构体，不需要结构体类名，只需要对象名称
                    //if(paraType != EXPR_STRUCT)
                    //{
                        newVar->name = pParaList->at(i);
                    /*}
                    else
                    {
                        //st.varname,只需要后面的varname即可
                        size_t pos = (*it).find(".");

                        newVar->name = (*it).substr(pos+1);
                    }
                    */
                    newVar->type = paraType;

                    if (FillSymNodeByExpr(newVar, expr, true) >= 0)
                    {
                        //定义一个新的形参栈变量，把变量入栈
                        //定义变量
                        expr.freeMem();

                        //这里不能入栈，要放入到后面根作用域之后。
                        paraSymList.append(newVar);
                        //加入到符号表中
                        //getPinSymTable()->append(newVar);
                    }
                    else
                    {
                        //参数和值不能匹配
                        QString errmsg = QString(u8"函数 %1 调用的第 %2 个参数 %3 类型无法匹配参数值！").arg(QString::fromStdString(name)).arg(QStr(pParaList->at(i))).arg(QString::fromStdString(arg->rightvar()->getText()));
                        AbortException(errmsg);
                        return 0;
                    }
                    //++it;

                }
            }


            //从现在开始，这里就是进入新函数的作用域了。
            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //遇到调用函数，把函数名入栈
            SymNode* node = new SymNode();
            #ifdef PIN_MEM_REF
            newTime();
#endif
            node->name = name;
            node->type = FUN_SYM;
            node->value.v2int.vint2 = ctx->getStart()->getLine();


            bool isFunNeedReturnValue = false;

            PinParser::Fun_retContext* pFunRet = nullptr;
            //这里记录一下，如果函数需要关注返回值，则设置
            //判断函数调用者，是否需要关注返回值。即调用函数有接受参数，或者显示返回需要返回值。

            //要结果，但是又没有fun_ret,直接return hs_xxx的方式。
            //20250214 加了一种模式：就是把函数返回值做表达式的情况。也走这里，类似于隐藏调用 return fun的方式。逻辑一样。
            if (ctxParent == nullptr)
            {
                //直接给出返回值，但是不赋值给外面的变量即可。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                if (pRetList == nullptr)
                {
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用函数 %3 没有返回值，不能接收该函数返回值 ！").arg(curLine).arg(curStatement).arg(QStr(name));
                    AbortException(errmsg);
                    return 0;
                }

                //需要关注函数的返回值。
                node->value.vint = NEED_FUN_RET_VALUE;
                isFunNeedReturnValue = true;

                //这里还是有点问题。需要把函数的值?
            }
            else
            {
                //一定是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。

                pFunRet = ctxParent->fun_ret();
                if (pFunRet != nullptr)
                {
                    std::vector<std::string>* pRetList = pFunInfo->retList;
                    if (pRetList == nullptr)
                    {
                        QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用函数 %3 没有返回值，不能接收该函数返回值 ！").arg(curLine).arg(QStr(ctxParent->getText())).arg(QStr(name));
                        AbortException(errmsg);
                        return 0;
                    }

                    //需要关注函数的返回值。
                    node->value.vint = NEED_FUN_RET_VALUE;
                    isFunNeedReturnValue = true;

                    antlr4::tree::TerminalNode* pAutoDef = pFunRet->FUN_RET_AUTO_DEF();
                    if (pAutoDef == nullptr)
                    {
                        //如果不是自动定义。检查返回的参数值是否存在，不存在就抛出异常
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                        for (auto retId : retIdVec)
                        {
                            std::string varStr = retId->getText();

                            if (varStr != "_")
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                if (varName.size() > 0 &&  !isLoaclVarAlreadyExist(varName))
                                {
                                    //返回值不存在于作用域52
                                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 变量 %3 参数未定义 ").arg(curLine).arg(curStatement).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                            }

                        }
                    }
                    else
                    {
                        //如果是自动定义，则参数不能和已有冲突
                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                        std::vector<std::string>* pRetList = pFunInfo->retList;

                        std::vector<std::string>::iterator it = pRetList->begin();

                        if (retIdVec.size() != pRetList->size())
                        {
                            QString errmsg = QString(u8"错误：函数中 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(name));
                            AbortException(errmsg);
                            return 0;
                        }

                        for (auto retId : retIdVec)
                        {
                            //PinParser::Ret_idContext* retId = retIdVec.at(i);

                            std::string varStr = retId->getText();

                            if (varStr != "_")
                            {
                                //检查参数是否存在。
                                std::string varName = getPinvarName(retId->pinvar());

                                if (isLoaclVarAlreadyExist(varName))
                                {
                                    //返回值参数已经存在

                                    QString errmsg = QString(u8"错误：函数 %1 语句 %2 变量 %3 已经在当前作用域中存在，不能重复使用 := 符号自动创建该变量 ").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctxParent->getText())).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                                else
                                {
                                    /*int type = getVarTypeByName(varStr);
                                    //自动创建这部分变量，创建之前，先判断是否参数合法
                                    if (exprTypeMatch(type, getVarTypeByName(*it), true) < 0)
                                    {
                                        QString errmsg = QString(u8"错误：返回参数 %1 和函数定义形参 %2 类型不匹配！").arg(QString::fromStdString(*it)).arg(QString::fromStdString(varStr));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                    else*/
                                    {
                                        //创建返回参数变量
                                        SymNode* newVar = new SymNode();
                        #ifdef PIN_MEM_REF
                            newTime();
                        #endif
                                        newVar->name = varStr;
                                        newVar->type = getVarTypeByName(*it);
                                        //后续会直接使用名称访问这些变量。
                                        getPinSymTable()->append(newVar);
                                    }

                                }
                            }
                            ++it;

                        }
                    }

                }
            }

            getPinSymTable()->push_back(node);

            //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
            //再加入一个根作用域。保证后续参数的定义，是在该作用域之后。
            //第一个作用域中的参数定义，不能覆盖形参，这是一个规则。所以这里要无条件插入一个作用域，表示函数的根作用域。
            SymNode* nodeScope = new SymNode;
            #ifdef PIN_MEM_REF
            newTime();
#endif
            nodeScope->type = SCOPE_SYM;
            //作用域反而是没有名称的。
            getPinSymTable()->push_back(nodeScope);

            //加入根作用域之后，再把参数入栈，顺序一定不能乱。保证形参是放在更作用域之后。
            for (auto v : paraSymList)
            {
                getPinSymTable()->push_back(v);
            }

            //表示刚刚函数的第一个块。后续进入块时，如果发现是根块， 不需要再加入作用域。
            pushStatus(INTO_FUN_FIRST_BLOCK_SCOPE);

            //执行函数体
            #ifdef PIN_DEBUG
            //std::cout << u8"将执行函数体代码" << *pBlock << std::endl;
            #endif

            antlr4::ANTLRInputStream bodyStream(*pBlock);

            PinLexer lexer(&bodyStream);

            CommonTokenStream tokens(&lexer);

            PinParser parser(&tokens);
            PinErrListener errListener;
            errListener.tokens = &tokens;

            parser.removeErrorListeners();
            parser.addErrorListener(&errListener);

            tree::ParseTree* tree = parser.block();
            ExprVisitor expr;
            expr.visit(tree);

            //函数体在执行完毕的时候，不需要销毁形参，因为形参变量已经在函数根作用域之上，根作用域销毁时已经销毁了它们。
            //销毁函数要注意，因为可能存在返回值在函数的栈变量上。

            //如果是通过fanhui 语句返回。
            if (getPinRunStatus() == FUNCTION_RET)
            {
                popStatus();

                //返回值在函数的作用域的valut.vpoint上面。
                if (isFunNeedReturnValue)
                {
                    //调用函数时，需要函数返回值
                    if (nullptr == node->funRetValue)
                    {
                        //看起来这下面的代码，应该是永远不走。
                        if (ctxParent != nullptr)
                        {
                        QString errmsg = QString(u8"错误：函数 %1 调用时缺少返回值，运行异常，请检查！").arg(QString::fromStdString(name));
                        AbortException(errmsg);
                        return 0;
                        }
                        else
                        {
                            //就是没有显示返回值的情况，无法把返回值写入参数变量
                            //先把返回值取出来。
                            QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                            node->funRetValue = nullptr;

                            //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                            deleteCurFunction();

                            //再直接把返回值写入到上层函数的返回值中。
                            setcurFunReturnValue(retList);

                            //务必返回，不能重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                    }
                    else
                    {
                        //有返回值的情况。检查返回值是否和调用者的变量匹配。

                        //是return hs_x 直接函数返回的情况，没有显示接收函数返回参数。
                        if (ctxParent == nullptr)
                        {

                            //就是没有显示返回值的情况，无法把返回值写入参数变量
                            //先把返回值取出来。
                            QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                            node->funRetValue = nullptr;

                            //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                            deleteCurFunction();

                            //在直接把返回值写入到上层函数的返回值中
                            setcurFunReturnValue(retList);

                            //务必返回，不能重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                        //先把返回值取出来。
                        QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);
                        node->funRetValue = nullptr;

                        //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                        deleteCurFunction();

                        //获取函数的返回值pFunRet
                        if (pFunRet == nullptr)
                        {
                            QString errmsg = QString(u8"错误：函数 %1 没有返回值，无法支持 fanhui %1 函数语句！").arg(QString::fromStdString(name));
                            AbortException(errmsg);
                            return 0;
                        }
                        else
                        {
                            //把函数返回值赋值。

                            std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                            QList<SymNode*>::iterator it = retList->begin();


                            for (auto retId : retIdVec)
                            {
                                std::string varStr = retId->getText();

                                if (varStr != "_")
                                {
                                    //注意这里*it反正后续要释放，这里掏空没有问题。
                                    ExprValue expr;
                                    expr.type = (*it)->type;
                                    expr.value.vpoint = (*it)->value.vpoint;
                                    (*it)->value.vint64 = 0;

                                    visitPinvar(retId->pinvar(),false, &expr);
                                    /*
                                    std::vector<PinParser::ListindexContext *> plistMap = retId->pinvar()->listindex();
                                    PinParser::StMemVarContext* pStructMem = retId->pinvar()->stMemVar();
                                    std::string varName = retId->pinvar()->VARNAME()->getText();

                                    SymNode* varNode = getVarFromSymTable(varName, ctx);

                                    if(plistMap.size() == 0 && pStructMem != nullptr)
                                    {
                                        assignStructMem(varNode, pStructMem, *it, ctxParent);

                                    }
                                    else if(retId->pinvar()->accesslist() != nullptr)
                                    {
                                        assignList(retId->pinvar()->accesslist(), *it, ctxParent);
                                    }
                                    else if(retId->pinvar()->accessmap() != nullptr)
                                    {
                                        assignMap(retId->pinvar()->accessmap(), *it, ctxParent);
                                    }
                                    //其余的直接按基本变量走
                                    else
                                    {
                                        SymNode* varNode = getVarFromSymTable(varStr, ctx);
                                        if (varNode != nullptr)
                                        {
                                            if (FillSymNodeBySymNode(varNode, *it) < 0)
                                            {
                                                QString errmsg = QString(u8"错误：变量 %1 不能使用 变量 %2 赋值，类型不匹配！").arg(QString::fromStdString(varNode->name)).arg(QString::fromStdString((*it)->name));
                                                AbortException(errmsg);
                                                return 0;
                                            }
                                        }
                                        else
                                        {
                                            QString errmsg = QString(u8"错误：找不到变量 %1，变量没有定义或书写错误，请检查 ！").arg(QString::fromStdString(varStr));
                                            AbortException(errmsg);
                                            return 0;
                                        }
                                    }
                                    */
                                }
                                //销毁返回值
                                (*it)->destory();
                                delete (*it);

#ifdef PIN_MEM_REF
                                freeTimes++;
#endif

                                ++it;
                            }

                            delete retList;
#ifdef PIN_MEM_REF
                            freeTimes++;
#endif

                            //务必返回，不能再重复销毁函数作用域
                            //destory_temp_para_ref(temp_para_ref);
                            return 0;
                        }
                    }
                }
                else
                {
                    //不需要返回值。则不应该返回值。
                    if (nullptr != node->funRetValue)
                    {
                        //参数和值不能匹配。不算致命错误。打印而不异常终止。
                        QString errmsg = QString(u8"警告：函数 %1 调用时不需要返回值，实际也有返回值！").arg(QString::fromStdString(name));
                        std::cout << errmsg.toStdString() << std::endl;


                        QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->funRetValue);

                        for (int i = 0, c = retList->size(); i < c; ++i)
                        {
                            retList->at(i)->destory();
                            delete retList->at(i);

#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                        }
                        delete retList;
                        node->funRetValue = nullptr;
#ifdef PIN_MEM_REF
                        freeTimes++;
#endif
                    }

                }
            }
            else
            {
                //自然返回，没有遇到fanhui语句。即不需要返回什么值。
                std::vector<std::string>* pRetList = pFunInfo->retList;
                //如果函数有返回参数，则必须要通过fanhui返回。
                if (pRetList != nullptr)
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"错误：函数 %1 体没有返回值,该函数形式需要返回值 ！").arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
            }
            //destory_temp_para_ref(temp_para_ref);
            deleteCurFunction();

        }
#endif
    }

    return 0;
}

std::any ExprVisitor::visitRealCallFun(PinParser::RealCallFunContext* ctx, PinParser::WithRetCallFunContext* ctxParent, int flag)
{
    //如果是链式多级调用,加上多级标记
    if ((ctx->multiCallFun().size() > 0))
    {
        flag |= MULTI_CALL_FUN;
    }

    ////不是调用自己写的函数，而是转调用底层qt封装的接口函数
    if (ctx->memberFunAccess() != nullptr)
    {
        visitCallQtFun(ctx, ctxParent, flag);
    }
    else
    {
        //判断是回调函数还是普通函数，分别执行
        std::string varName = ctx->VARNAME()->getText();

        SymNode* pHdFun = getVarFromSymTable(varName, ctx);
        if (pHdFun->type == EXPR_CALL_BACK_FUN)
        {
            //加入关键信息函数。帮助错误的时候定位信息。
            //这里不要叫错误信息了，要叫回调函数hd 映射为全局函数 hs 的一个转换关系。
            SymNode* pHdSym = new SymNode;
            pHdSym->type = HD_TO_HS_INFO;

#ifdef PIN_MEM_REF
            newTime();
#endif
            //回调函数也按函数的信息统一处理。但是有一点，回调函数的名称不能直接如运行栈，因为已经有同名的参数了。
            pHdSym->name = std::to_string(ctx->getStart()->getLine()) + "@" + varName; //名称是回调函数的名称。这里varName已经有对象了，必须要改名。

            //SymNode* pSym = getVarFromSymTable(varName, ctx);

            //一定要放在getVarFromSymTable的下面，否则就是自己获取自己了。
            getPinSymTable()->push_back(pHdSym);

            //std::cout << "---fun line " << ctx->getStart()->getLine() << std::endl;

            std::string funName = *(std::string*)(pHdFun->value.vpoint);

            pHdSym->value.vpoint = new std::string(funName); //值是对应的全局函数的名称。
#ifdef PIN_MEM_REF
            newTime();
#endif

            visitRealCallNormalFun(ctx, ctxParent, funName, ctx->argumentList(), flag);

#if 0
                std::string codeSrc = ctx->getText();

                //以 xxx := hd_ 或 xxx = hd_ 的方式 即withRetCallFun
                if (ctxParent != nullptr)
                {
                    codeSrc = ctxParent->getText();
                }
                else
                {
                    //在这种情况下，callFun其实被分割为两节，后面一截没有只有callRealFun,没有带上;号。
                    codeSrc += ";";
                }

                if (getRetValue)
                {
                    //这里不能这样，否则导致两次调用fanhui
                    //是关心结果的，但是ctxParent却是空，说明是以 fanhui hd_x 的形式。把代码补齐。
                    //codeSrc = "fanhui " + codeSrc;
                    //使用pinstatus变相实现。这里不删除，留着。是个教训。
                    pushStatus(CALL_BACK_FUN_NEED_RETVALUE);
                }


                //把varName替换为funName后，再次执行函数语句
                replaceAll(codeSrc, varName, funName);

                //如果没有;号结尾，必须加一个;号才行,否则没法走callFun语句。

                //执行真正的函数调用语句
                antlr4::ANTLRInputStream bodyStream(codeSrc);

                PinLexer lexer(&bodyStream);

                CommonTokenStream tokens(&lexer);

                PinParser parser(&tokens);
                PinErrListener errListener;
                errListener.tokens = &tokens;

                parser.removeErrorListeners();
                parser.addErrorListener(&errListener);

#if 1
                tree::ParseTree* tree = parser.callFun();

                //这里还是有些问题，发现 hs_callback(zs_1) 后面没有;号，走realCallFun时，居然没法走，真是奇怪，可能哪里有bug。还是优先匹配了callFun
                //但是现在callFun必须要带一个；号，call_back函数现在没法直接执行。
#else
                tree::ParseTree* tree = nullptr;
                if (ctxParent != nullptr)
                {
                    //xxx := hd_ xxx = hd_ 的方式，必须要以callfun调用
                    tree = parser.callFun();
                }
                else
                {
                    tree = parser.realCallFun(); //其余，只需要以realcallfun调用。 发现错误，还是要callFun,二次确认这里有错，不会走这。
                }
#endif
                ExprVisitor expr;
                expr.visit(tree);
#endif

             //及时把这个临时节点删除，避免不必要的麻烦。
             deleteCurScopeVar(pHdSym);
        }
        else
        {
            //非回调函数，就是普通函数的情况。
            visitRealCallNormalFun(ctx, ctxParent, flag);
        }

    }

    //再执行链式调用。
    std::vector<PinParser::MultiCallFunContext *> pMultiFun = ctx->multiCallFun();
    if(pMultiFun.size() > 0)
    {
        //执行完毕后，取出函数的返回值
        QList<SymNode*>* retList = getcurFunReturnValue();

        if (retList == nullptr || retList->size() == 0)
        {
            std::string funName = ctx->memberFunAccess()->getText();
            QString msg = QString(u8"错误：行号 %1 语句 %2 函数 %3 没有返回值，其返回值无法做表达式进一步求解后操作！").arg(curLine).arg(curStatement).arg(QStr(funName));
            AbortException(msg);
        }

        //取出第一个，做返回值，然后
        SymNode* pRet = retList->at(0);

        //销毁其它的返回值。
        for (int i =1, c = retList->size(); i < c; ++i)
        {
            retList->at(i)->destory();
            delete retList->at(i);

            #ifdef PIN_MEM_REF
                   freeTimes++;
            #endif
        }

        delete retList;
        #ifdef PIN_MEM_REF
                freeTimes++;
        #endif
        setcurFunReturnValue(nullptr);

        //根据当前的返回值，伪造一个临时变量，
        //pRet->name = createTempVarNameByType(pRet->type);

        std::string callfunCodePre;

        if(ctx->memberFunAccess() != nullptr)
        {
            //取出调用部分的前缀
            callfunCodePre = ctx->memberFunAccess()->getText();

            if(ctx->argumentList() != 0)
            {
                callfunCodePre += "(" + ctx->argumentList()->getText()+ ")";
            }
            else
            {
                callfunCodePre += "()";
            }
        }
        else
        {
            //取出调用部分的前缀
            callfunCodePre = ctx->VARNAME()->getText();

            if(ctx->argumentList() != 0)
            {
                callfunCodePre += "(" + ctx->argumentList()->getText()+ ")";
            }
            else
            {
                callfunCodePre += "()";
            }
        }

        if(!multiCallTempObjIsVaild(pRet->type))
        {
            std::string funMsg;

            for(int j=0, jc = pMultiFun.size(); j < jc; ++j)
            {
                funMsg += pMultiFun.at(j)->getText();
            }

            //当前类型不是合法可以继续调用函数的对象
            QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用部分 %3 的返回值无法继续调用后续方法 %4").arg(curLine).arg(curStatement).arg(QStr(callfunCodePre)).arg(QStr(funMsg));
            AbortException(errmsg);
        }

        //把返回值，加入到当前作用域中。???先屏蔽，感觉没必要加入，多次一举。
        //getPinSymTable()->append(pRet);

        //这里要进入多级调用，要类似HD_TO_HS_INFO一样，记住当前调用的位置。可以理解为就是一个转义调用。
        SymNode* pHdSym = new SymNode;
        pHdSym->type = HD_TO_HS_INFO;

#ifdef PIN_MEM_REF
        newTime();
#endif
        //回调函数也按函数的信息统一处理。但是有一点，回调函数的名称不能直接如运行栈，因为已经有同名的参数了。
        pHdSym->name = std::to_string(ctx->getStart()->getLine()) + u8"@链式执行"; //名称是回调函数的名称。这里varName已经有对象了，必须要改名。

        //QString info = QString("%1")
        //现在ctx已经是外面整个语句的字符串。
        pHdSym->value.vpoint = new std::string(ctx->getText()); //值是对应的全局函数的名称。
#ifdef PIN_MEM_REF
        newTime();
#endif
        getPinSymTable()->push_back(pHdSym);

        //bool isMutiNeedRetValue = false;
        //是多级调用，在返回值的基础上，继续一级一级的去调用
        for(int i=0,c=pMultiFun.size(); i <c ;++i)
        {
            /*if (i < c - 1)
            {
                //多级调用，必须要返回值。
                isMutiNeedRetValue = true;
            }
            else if (getRetValue)
            {
                //最后一个,得看外面是否需要返回值。
                isMutiNeedRetValue = getRetValue;
            }*/
            //最后一级，
            if (i == c - 1)
            {
                flag |= MULTI_CALL_LAST_CALL_FUN;
            }

            ExprValue objExpr;
            objExpr.varName = &callfunCodePre; //把调用部分的名称传递到下面去，后面报错要使用。
            objExpr.type = pRet->type;

            //链式调用的时候，后面的调用是使用前面的返回值。这里已经有前面返回值的的指针了。
            // 后续底层要修改原始值的时候，没必要再获取原始变量。

            //这里必须要浅拷贝一下
            objExpr.value.vpoint = pRet->value.vpoint;
            addListMapRefNum(objExpr);

#if 0
            SymNode* pFunSym = new SymNode();
#ifdef PIN_MEM_REF
            newTime();
#endif
            pFunSym->name = pRet->name + "ctx";
            pFunSym->type = EXPR_MULTI_FUN_CALL_CTX;
            pFunSym->value.vpoint = ctx;

            getPinSymTable()->append(pFunSym);
#endif

            PinParser::MultiCallFunContext* pFunCtx = pMultiFun.at(i);
            std::string funName = pFunCtx->VARNAME()->getText();
            pHdSym->name = std::to_string(ctx->getStart()->getLine()) + "@" + funName; //名称是回调函数的名称。这里varName已经有对象了，必须要改名。


            visitCallQtFun(ctx,ctxParent, objExpr, funName,
                pFunCtx->argumentList(), false, flag);

            //把前面的临时变量删除一下
            pRet->destory();
            delete pRet;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
            pRet = nullptr;
            //deleteCurScopeVar(pRet);
            //deleteCurScopeVar(pFunSym);

            if (i < c - 1)
            {
                //执行完毕后，取出函数的返回值
                QList<SymNode*>* retList = getcurFunReturnValue();
                if (retList == nullptr || retList->size() == 0)
                {

                    std::string funMsgBefore = callfunCodePre;

                    for (int j = 0; j <= i; ++j)
                    {
                        funMsgBefore += pMultiFun.at(j)->getText();
                    }

                    std::string funMsgAfter;

                    for (int j = i + 1, jc = pMultiFun.size(); j < jc; ++j)
                    {
                        funMsgAfter += pMultiFun.at(j)->getText();
                    }

                    QString msg = QString(u8"错误：行号 %1 语句 %2 调用部分 %3 没有返回值，无法继续调用后续 %4！").arg(curLine).arg(curStatement).arg(QStr(funMsgBefore)).arg(QStr(funMsgAfter));
                    AbortException(msg);
                }

                pRet = retList->at(0);

                //销毁其它的返回值
                for (int i = 1, c = retList->size(); i < c; ++i)
                {
                    retList->at(i)->destory();
                    delete retList->at(i);

#ifdef PIN_MEM_REF
                    freeTimes++;
#endif
                }
                delete retList;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
                setcurFunReturnValue(nullptr);

                //根据当前的返回值，伪造一个临时变量，
                //pRet->name = createTempVarNameByType(pRet->type);

                if (!multiCallTempObjIsVaild(pRet->type))
                {
                    //当前类型不是合法可以继续调用函数的对象
                    //QString errmsg = QString(u8"错误：行号 %1 语句 %2 的返回值无法继续调用后续方法").arg(curLine).arg(curStatement);
                    //AbortException(errmsg);
                    std::string funMsgBefore = callfunCodePre;
                    for (int j = 0; j <= i; ++j)
                    {
                        funMsgBefore += pMultiFun.at(j)->getText();
                    }

                    std::string funMsgAfter;

                    for (int j = i + 1, jc = pMultiFun.size(); j < jc; ++j)
                    {
                        funMsgAfter += pMultiFun.at(j)->getText();
                    }

                    //当前类型不是合法可以继续调用函数的对象
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用部分 %3 的返回值是 %4 无法继续调用后续方法 %5").arg(curLine).arg(curStatement).arg(QStr(funMsgBefore)).arg(getExpeTypeValue(pRet->type)).arg(QStr(funMsgAfter));
                    AbortException(errmsg);
                }
                //把返回值，加入到当前作用域中。
                //getPinSymTable()->append(pRet);

                //最后一个pRet在这里面没有删除，不过还是在作用域上，函数返回之前，作用域会自动删除掉。没问题。
            }
            else
            {
                //最后一个，直接返回
                if(pRet != nullptr)
                {
                pRet->destory();
                delete pRet;
#ifdef PIN_MEM_REF
                freeTimes++;
#endif
                pRet = nullptr;
                }
                 //及时把这个临时节点删除，避免不必要的麻烦。
                deleteCurScopeVar(pHdSym);

                return 0;
            }

            //不使用二次翻译的路线了，直接调用函数。
#if 0
            if(i < c-1)
            {
                //多级调用，必须要返回值。
                pushStatus(CALL_BACK_FUN_NEED_RETVALUE);
            }
            else if(getRetValue)
            {
                //最后一个,得看外面是否需要返回值。
                pushStatus(CALL_BACK_FUN_NEED_RETVALUE);
            }

            std::string codeSrc = pRet->name + pMultiFun.at(i)->getText() + ";";

            antlr4::ANTLRInputStream bodyStream(codeSrc);

            PinLexer lexer(&bodyStream);

            CommonTokenStream tokens(&lexer);

            PinParser parser(&tokens);
            PinErrListener errListener;
            errListener.tokens = &tokens;

            parser.removeErrorListeners();
            parser.addErrorListener(&errListener);

            SymNode* pFunSym = new SymNode();
#ifdef PIN_MEM_REF
        newTime();
#endif
            pFunSym->name = pRet->name + "ctx";
            pFunSym->type = EXPR_MULTI_FUN_CALL_CTX;
            pFunSym->value.vpoint = ctx;


            getPinSymTable()->append(pFunSym);

            tree::ParseTree* tree = parser.callFun();

            ExprVisitor expr;
            expr.visit(tree);

                //把前面的临时变量删除一下
                QList<SymNode*>* pSymlist = getPinSymTable();

                int index = pSymlist->indexOf(pRet);
                if(index != -1)
                {
                    pSymlist->removeAt(index);
                    pRet->destory();
                    delete pRet;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }

                index = pSymlist->indexOf(pFunSym);
                if(index != -1)
                {
                    pSymlist->removeAt(index);
                    pFunSym->destory();
                    delete pFunSym;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }

            if(i < c-1)
            {
                //执行完毕后，取出函数的返回值
                QList<SymNode*>* retList = getcurFunReturnValue();
                if (retList == nullptr || retList->size() == 0)
                {
                    //std::string funName = ctx->memberFunAccess()->getText();

                    std::string funMsgBefore = callfunCodePre;

                    for(int j=0; j <= i; ++j)
                    {
                        funMsgBefore += pMultiFun.at(j)->getText();
                    }

                    std::string funMsgAfter;

                    for(int j=i+1, jc = pMultiFun.size(); j < jc; ++j)
                    {
                        funMsgAfter += pMultiFun.at(j)->getText();
                    }

                    QString msg = QString(u8"错误：行号 %1 语句 %2 调用部分 %3 没有返回值，无法继续调用后续 %4！").arg(curLine).arg(curStatement).arg(QStr(funMsgBefore)).arg(QStr(funMsgAfter));
                    AbortException(msg);
                }



                //取出第一个，做返回值，然后
                //ExprValue ret;
                //ret.type = retList->at(0)->type;
                //FillExprBySymNode(&ret, retList->at(0),ctx);

                pRet = retList->takeAt(0);


                //销毁其它的返回值
                for (int i = 1, c = retList->size(); i < c; ++i)
                {
                    retList->at(i)->destory();
                    delete retList->at(i);

        #ifdef PIN_MEM_REF
                    freeTimes++;
        #endif
                }
                delete retList;
        #ifdef PIN_MEM_REF
                freeTimes++;
        #endif
                setcurFunReturnValue(nullptr);

                //根据当前的返回值，伪造一个临时变量，
                pRet->name = createTempVarNameByType(pRet->type);

                if(pRet->name == "error")
                {
                    //当前类型不是合法可以继续调用函数的对象
                    //QString errmsg = QString(u8"错误：行号 %1 语句 %2 的返回值无法继续调用后续方法").arg(curLine).arg(curStatement);
                    //AbortException(errmsg);
                    std::string funMsgBefore = callfunCodePre;
                    for(int j=0; j <= i; ++j)
                    {
                        funMsgBefore += pMultiFun.at(j)->getText();
                    }

                    std::string funMsgAfter;

                    for(int j=i+1, jc = pMultiFun.size(); j < jc; ++j)
                    {
                        funMsgAfter += pMultiFun.at(j)->getText();
                    }

                    //当前类型不是合法可以继续调用函数的对象
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2 调用部分 %3 的返回值是 %4 无法继续调用后续方法 %5").arg(curLine).arg(curStatement).arg(QStr(funMsgBefore)).arg(getExpeTypeValue(pRet->type)).arg(QStr(funMsgAfter));
                    AbortException(errmsg);
                }
                //把返回值，加入到当前作用域中。
                getPinSymTable()->append(pRet);

                //最后一个pRet在这里面没有删除，不过还是在作用域上，函数返回之前，作用域会自动删除掉。没问题。
            }
            else
            {
                //最后一个，直接返回
                 //及时把这个临时节点删除，避免不必要的麻烦。
                deleteCurScopeVar(pHdSym);

                return 0;
            }
#endif
        }

    }

    return 0;
}



//以不关心函数返回值的方式调用函数。虽然不关心，但是如果有多级调用，其实中间还是需要返回值的，要注意逻辑。
std::any ExprVisitor::visitNoRetCallFun(PinParser::NoRetCallFunContext* ctx)
{
    return visitRealCallFun(ctx->realCallFun(), nullptr, NO_NEED_RETURN);
}

//以关心函数返回值的方式调用函数
std::any ExprVisitor::visitWithRetCallFun(PinParser::WithRetCallFunContext* ctx)
{
    return visitRealCallFun(ctx->realCallFun(), ctx, NEED_RETURN);
}

//以 fanhui xxx 的方式访问函数。
std::any ExprVisitor::visitReturnCallFun(PinParser::ReturnCallFunContext* ctx)
{

#ifdef PIN_DEBUG
    std::cout << "--- visitReturnCallFun" << ctx->getText() << std::endl;
#endif
    //20250410加入了多级调用，下面的逻辑只能检查非多级。
    bool isMultiCall = (ctx->realCallFun()->multiCallFun().size() > 0);
    //直接返回函数。由于是return funcion的方式。看看函数的上级调用者，是否关注返回值。
    //如果不关注，则不需要返回值；反之需要。
    if (isFunNeedReturnValue())
    {


        bool is_call_back_fun = false;

        //如果不是多级调用，则检查一下。否则不检查了，因为多级要检查的是最后一级函数。
        if (!isMultiCall && ctx->realCallFun()->VARNAME() != nullptr)
        {

            SymNode* pHdFun = getVarFromSymTable(ctx->realCallFun()->VARNAME()->getText(),ctx);
            if(pHdFun->type == EXPR_CALL_BACK_FUN)
            {
                //如果是函数，表示是函数做参数，那么函数要视作回调函数处理
                is_call_back_fun = true;
            }
            else
            {
            //对函数返回值 与 函数形参进行匹配，看能否匹配。
            //获取当前函数需要的返回值。
            //当前函数的返回参数列表
            std::string funName;
            std::vector<std::string>* pRetList = curFunRetPara(&funName);

            //被调用函数的返回值
            std::string callFunName = ctx->realCallFun()->VARNAME()->getText();

            FUN_SYM_INFO* symInfo = findFunBlock(callFunName);
            if (symInfo == nullptr)
            {
                QString errmsg = QString(u8"错误：行号 %1 找不到函数 %2 函数 %3 语句 %4 ！").arg(curLine).arg(QString::fromStdString(callFunName))
                    .arg(QString::fromStdString(funName)).arg(QString::fromStdString(ctx->getText()));

                AbortException(errmsg);
                return 0;
            }
            std::vector<std::string>* pCallFunRetList = symInfo->retList;

            if (pCallFunRetList == nullptr && pRetList == nullptr)
            {
                //都是空
            }
            else if (pCallFunRetList != nullptr && pRetList != nullptr && pCallFunRetList->size() == pRetList->size())
            {
                //都存在，而且数量一样，进一步检查类型匹配。
                std::vector<std::string>::iterator it = pCallFunRetList->begin();

                for (auto ret : *pRetList)
                {
                    if (exprTypeMatch(getVarTypeByName(ret), getVarTypeByName(*it), true) < 0)
                    {
                        QString errmsg = QString(u8"错误：函数 %1 语句 %2 ，函数%3的返回值类型，不能匹配函数 %1 的定义类型 ！").arg(QString::fromStdString(funName))
                            .arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(callFunName));

                        AbortException(errmsg);
                    }
                    ++it;
                }
            }
            else
            {
                QString errmsg = QString(u8"错误：行号 %1 语句 %2 ，函数%3的返回值形式不能匹配函数 %1 的定义形式 ！").arg(curLine)
                    .arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(callFunName));

                AbortException(errmsg);
                return 0;
            }
            }
        }

        if (is_call_back_fun /*ctx->realCallFun()->CALL_FUN() != nullptr*/)
        {
            //调用回调函数
            //获取当前函数需要的返回值。
            //当前函数的返回参数列表
            std::string funName;
            std::vector<std::string>* pRetList = curFunRetPara(&funName);



            //回调函数
            std::string srcFunName = ctx->realCallFun()->VARNAME()->getText();

            SymNode* pSym = getVarFromSymTable(srcFunName, ctx);

            std::string callFunName = *(std::string*)(pSym->value.vpoint);


            FUN_SYM_INFO* symInfo = findFunBlock(callFunName);
            if (symInfo == nullptr)
            {
                QString errmsg = QString(u8"错误：找不到函数 %1 函数 %2 语句 %3 ！").arg(QString::fromStdString(callFunName))
                    .arg(QString::fromStdString(funName)).arg(QString::fromStdString(ctx->getText()));

                AbortException(errmsg);
                return 0;
            }
            std::vector<std::string>* pCallFunRetList = symInfo->retList;

            if (pCallFunRetList == nullptr && pRetList == nullptr)
            {
                //都是空
            }
            else if (pCallFunRetList != nullptr && pRetList != nullptr && pCallFunRetList->size() == pRetList->size())
            {
                //都存在，而且数量一样，进一步检查类型匹配。
                std::vector<std::string>::iterator it = pCallFunRetList->begin();

                for (auto ret : *pRetList)
                {
                    if (exprTypeMatch(getVarTypeByName(ret), getVarTypeByName(*it), true) < 0)
                    {
                        QString errmsg = QString(u8"错误：行号 %1 函数 %2 语句 %3 ，回调函数 %4 调用的函数%5 的返回值类型，不能匹配函数 %2 的定义类型 ！").arg(curLine).arg(QString::fromStdString(funName))
                            .arg(QString::fromStdString(ctx->getText())).arg(QStr(srcFunName)).arg(QStr(callFunName));

                        AbortException(errmsg);
                    }
                    ++it;
                }
            }
            else
            {
                QString errmsg = QString(u8"错误：行号 %1 函数 %2 语句 %3 ，回调函数 %4 调用的函数%5 的返回值形式不能匹配函数 %2 的定义形式 ！").arg(curLine).arg(QString::fromStdString(funName))
                    .arg(QString::fromStdString(ctx->getText())).arg(QStr(srcFunName)).arg(QStr(callFunName));

                AbortException(errmsg);
                return 0;
            }
        }
        //如果是调用内部函数，则先不做检查。

        visitRealCallFun(ctx->realCallFun(), nullptr, NEED_RETURN);

        //到这里的时候，该函数本身的返回值，已经被设置为调用函数的返回值。
    }
    else
    {
        //检查一些错误的情况：使用fanhui xxx 返回，但是外部调用的函数，定义时没有返回值。给出告警。
        std::string funName;
        std::vector<std::string>* pRetList = curFunRetPara(&funName);
        if (pRetList == nullptr || pRetList->empty())
        {
            QString msg = QString(u8"警告：行号 %1 语句 %2 函数%3 定义没有返回参数，代码中却使用了fanhui 语句，将丢弃返回值！")
                .arg(curLine).arg(curStatement).arg(QStr(funName));
            std::cout << msg.toStdString() << std::endl;
        }
        //不关心函数结果。
        visitRealCallFun(ctx->realCallFun(), nullptr, NO_NEED_RETURN);
    }

    //进入函数返回模式。一旦进入该模式，后续语句不再执行。
    pushStatus(FUNCTION_RET);

    return 0;
}


#if 0
//调用函数。在这里面建立作用域的栈
std::any ExprVisitor::visitCallFun(PinParser::CallFunContext* ctx)
{
    std::string name = ctx->FUN_NAME()->getText();
    std::cout << u8"进入调用函数" << name << std::endl;

	//查找函数体
    FUN_SYM_INFO* pFunInfo = findFunBlock(name);
	if (pFunInfo == nullptr) {
        std::cout << u8"调用函数失败 函数名称 " << name << std::endl;

        QString errmsg = QString(u8"无法找到函数 %1 的定义！").arg(QString::fromStdString(name));
        std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

        std::rethrow_exception(eptr);
        return 0;
	}
    else
    {
        std::string* pBlock = pFunInfo->funBlock;
        std::list<std::string>* pParaList = pFunInfo->paraList;
        PinParser::ArgumentListContext* pArglist = ctx->argumentList();

        //检查调用参数个数能否匹配
        if (pParaList == nullptr && pArglist == nullptr)
        {
            //没有参数，匹配。
        }
        else if (pParaList != nullptr && pArglist != nullptr)
        {
            std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();
            if (pParaList->size() != argVec.size())
            {
                QString errmsg = QString(u8"函数 %1 语句 %2 调用的参数和函数定义无法匹配！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText()));
                AbortException(errmsg);
            }
        }
        else
        {
            QString errmsg = QString(u8"调用函数 %1 的参数和其定义无法匹配！").arg(QString::fromStdString(name));
            AbortException(errmsg);

            return 0;
        }

        QList<SymNode*> paraSymList;

        //先把函数的参数求值一下，现在还是在调用者的栈上面，前面注意。
        if (pArglist != nullptr)
        {
            //如果有参数，进入求参数值，而且把结构入栈的情况
            std::vector<PinParser::ArgumentContext*> argVec = pArglist->argument();

            //访问每个参数表达式
            std::list<std::string>::iterator it = pParaList->begin();

            for (PinParser::ArgumentContext* arg : argVec)
            {
                //进入表达式求值
                ExprValue expr = std::any_cast<ExprValue>(visit(arg->expr()));

                //形参 和 表达式类型是否匹配
                int paraType = getVarTypeByName(*it);

                SymNode* newVar = new SymNode();
                newVar->name = *it;
                newVar->type = paraType;

                if (FillSymNodeByExpr(newVar, expr, true) >= 0)
                {
                    //定义一个新的形参栈变量，把变量入栈
                    //定义变量
                    expr.freeMem();

                    //这里不能入栈，要放入到后面根作用域之后。
                    paraSymList.append(newVar);
                    //加入到符号表中
                    //getPinSymTable()->append(newVar);
                }
                else
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"函数 %1 调用的第 %2 个参数 %3 类型无法匹配参数值！").arg(QString::fromStdString(name)).arg(QString::fromStdString(*it)).arg(QString::fromStdString(arg->expr()->getText()));
                    AbortException(errmsg);
                    return 0;
                }
                ++it;

            }
        }


        //从现在开始，这里就是进入新函数的作用域了。
        //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
        //遇到调用函数，把函数名入栈
        SymNode* node = new SymNode();
        node->name = name;
        node->type = FUN_SYM;

        bool isFunNeedReturnValue = false;

        PinParser::Fun_retContext* pFunRet = nullptr;
        //这里记录一下，如果函数需要关注返回值，则设置
        //判断函数调用者，是否需要关注返回值。即调用函数有接受参数，或者显示返回需要返回值。
        //如果是使用 fanhui hs_hanshu的方式调用，但是关注返回值。
        if (getPinRunStatus() == FUNCTION_RET_NEED_RETVALUE)
        {
            node->value.vint = NEED_FUN_RET_VALUE;
            popStatus();
            isFunNeedReturnValue = true;

            //这种形式下，必然不能有fun_ret
            /*
            pFunRet = ctx->fun_ret();

            //必然不能有返回值，因为是fanhui hs_xx 的方式。
            if (pFunRet != nullptr)
            {
                QString errmsg = QString(u8"错误：函数 %1 语句 %2 没有返回值，无法支持 fanhui %1 函数语句！").arg(QString::fromStdString(name)).arg(QString::fromStdString(ctx->getText()));
                AbortException(errmsg);
                return 0;
            }
            */
        }
        else if (getPinRunStatus() == FUNCTION_RET_NO_NEED_RETVALUE)
        {
            //由于上级调用时 funhui hs_xxx 的形式，不关注返回值。所以调用时不关心返回值。
            popStatus();
            //这里不需要检查参数是否匹配，在调用的时候就检查过了。
        }
        else
        {
            //如果是使用 xxx := hs_hx 或 xx = hs_hx 的方式。这种必然有返回值。

            pFunRet = ctx->fun_ret();
            if (pFunRet != nullptr)
            {
                std::list<std::string>* pRetList = pFunInfo->retList;
                if (pRetList == nullptr)
                {
                    QString errmsg = QString(u8"错误：函数 %1 没有返回值，不能接收该函数返回值 ！").arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }

                //需要关注函数的返回值。
                node->value.vint = NEED_FUN_RET_VALUE;
                isFunNeedReturnValue = true;

                antlr4::tree::TerminalNode* pAutoDef = pFunRet->FUN_RET_AUTO_DEF();
                if (pAutoDef == nullptr)
                {
                    //如果不是自动定义。检查返回的参数值是否存在，不存在就抛出异常
                    std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                    for (auto retId : retIdVec)
                    {
                        std::string varStr = retId->getText();

                        if (varStr != "_")
                        {
                            if (!isLoaclVarAlreadyExist(varStr))
                            {
                                //返回值不存在于作用域
                                QString errmsg = QString(u8"错误：变量 %1 参数未定义 ").arg(QString::fromStdString(varStr));
                                AbortException(errmsg);
                                return 0;
                            }
                        }

                    }
                }
                else
                {
                    //如果是自动定义，则参数不能和已有冲突
                    std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();

                    std::list<std::string>* pRetList = pFunInfo->retList;

                    std::list<std::string>::iterator it = pRetList->begin();

                    if (retIdVec.size() != pRetList->size())
                    {
                        QString errmsg = QString(u8"错误：函数中 %1 语句 %2 函数 %3 返回值个数与函数定义形式不匹配 ！").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(name));
                        AbortException(errmsg);
                        return 0;
                    }
                    for (auto retId : retIdVec)
                    {
                        std::string varStr = retId->getText();

                        if (varStr != "_")
                        {
                            if (isLoaclVarAlreadyExist(varStr))
                            {
                                //返回值参数已经存在

                                QString errmsg = QString(u8"错误：函数 %1 语句 %2 变量 %3 已经在当前作用域中存在，不能重复使用 := 符号自动创建该变量 ").arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(varStr));
                                AbortException(errmsg);
                                return 0;
                            }
                            else
                            {
                                int type = getVarTypeByName(varStr);
                                //自动创建这部分变量，创建之前，先判断是否参数合法
                                if (exprTypeMatch(type, getVarTypeByName(*it), true) < 0)
                                {
                                    QString errmsg = QString(u8"错误：返回参数 %1 和函数定义形参 %2 类型不匹配！").arg(QString::fromStdString(*it)).arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                                else
                                {
                                    //创建返回参数变量
                                    SymNode* newVar = new SymNode();
                                    newVar->name = varStr;
                                    newVar->type = type;
                                    //后续会直接使用名称访问这些变量。
                                    getPinSymTable()->append(newVar);
                                }

                            }
                        }
                        ++it;

                    }
                }

            }
            //else就是不是上面方式，直接 hs_hx 方式
        }

        getPinSymTable()->push_back(node);

        //这里千万不能放在参数入栈的前面，会导致形参求值时，作用域错误，无法找到定义的变量。
        //再加入一个根作用域。保证后续参数的定义，是在该作用域之后。
        //第一个作用域中的参数定义，不能覆盖形参，这是一个规则。所以这里要无条件插入一个作用域，表示函数的根作用域。
        SymNode* nodeScope = new SymNode;
        nodeScope->type = SCOPE_SYM;
        //作用域反而是没有名称的。
        getPinSymTable()->push_back(nodeScope);

        //加入根作用域之后，再把参数入栈，顺序一定不能乱。保证形参是放在更作用域之后。
        for (auto v : paraSymList)
        {
            getPinSymTable()->push_back(v);
        }

        //表示刚刚函数的第一个块。后续进入块时，如果发现是根块， 不需要再加入作用域。
        pushStatus(INTO_FUN_FIRST_BLOCK_SCOPE);

        //执行函数体
        std::cout << u8"将执行函数体代码" << *pBlock << std::endl;

        antlr4::ANTLRInputStream bodyStream(*pBlock);

        PinLexer lexer(&bodyStream);

        CommonTokenStream tokens(&lexer);

        PinParser parser(&tokens);
        PinErrListener errListener;
        parser.removeErrorListeners();
        parser.addErrorListener(&errListener);

        tree::ParseTree* tree = parser.block();
        ExprVisitor expr;
        expr.visit(tree);

        //函数体在执行完毕的时候，不需要销毁形参，因为形参变量已经在函数根作用域之上，根作用域销毁时已经销毁了它们。
        //销毁函数要注意，因为可能存在返回值在函数的栈变量上。

        //如果是通过fanhui 语句返回。
        if (getPinRunStatus() == FUNCTION_RET)
        {
            popStatus();

            //返回值在函数的作用域的valut.vpoint上面。
            if (isFunNeedReturnValue)
            {
                //调用函数时，需要函数返回值
                if (nullptr == node->value.vpoint)
                {
                    QString errmsg = QString(u8"错误：函数 %1 调用时缺少返回值，运行异常，请检查！").arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
                else
                {
                    //有返回值的情况。检查返回值是否和调用者的变量匹配。

                    //先把返回值取出来。
                    QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->value.vpoint);
                    node->value.vpoint = nullptr;

                    //再把当前函数的作用域销毁，这样就进入了上层调用者的作用域中去了。
                    deleteCurFunction();

                    //获取函数的返回值pFunRet
                    if (pFunRet == nullptr)
                    {
                        QString errmsg = QString(u8"错误：函数 %1 没有返回值，无法支持 fanhui %1 函数语句！").arg(QString::fromStdString(name));
                        AbortException(errmsg);
                        return 0;
                    }
                    else
                    {
                        //把函数返回值赋值。

                        std::vector<PinParser::Ret_idContext*> retIdVec = pFunRet->ret_id();
                        QList<SymNode*>::iterator it = retList->begin();

                        for (auto retId : retIdVec)
                        {
                            std::string varStr = retId->getText();
                            if (varStr != "_")
                            {
                                SymNode* varNode = getVarFromSymTable(varStr);
                                if (varNode != nullptr)
                                {
                                    if (FillSymNodeBySymNode(varNode, *it) < 0)
                                    {
                                        QString errmsg = QString(u8"错误：变量 %1 不能使用 变量 %2 赋值，类型不匹配！").arg(QString::fromStdString(varNode->name)).arg(QString::fromStdString((*it)->name));
                                        AbortException(errmsg);
                                        return 0;
                                    }
                                }
                                else
                                {
                                    QString errmsg = QString(u8"错误：找不到变量 %1，变量没有定义或书写错误，请检查 ！").arg(QString::fromStdString(varStr));
                                    AbortException(errmsg);
                                    return 0;
                                }
                            }
                            //销毁返回值
                            (*it)->destory();
                            delete (*it);

#ifdef PIN_MEM_REF
                            freeTimes++;
#endif

                            ++it;
                        }

                        delete retList;
#ifdef PIN_MEM_REF
                        freeTimes++;
#endif

                        //务必返回，不能再重复销毁函数作用域
                        return 0;
                    }
                }
            }
            else
            {
                //不需要返回值。则不应该返回值。
                if (nullptr != node->value.vpoint)
                {
                    //参数和值不能匹配。不算致命错误。打印而不异常终止。
                    QString errmsg = QString(u8"警告：函数 %1 调用时不需要返回值，实际也有返回值！").arg(QString::fromStdString(name));
                    std::cout << errmsg.toStdString() << std::endl;


                    QList<SymNode*>* retList = static_cast<QList<SymNode*>*>(node->value.vpoint);

                    for (int i = 0, c = retList->size(); i < c; ++i)
                    {
                        retList->at(i)->destory();
                        delete retList->at(i);

#ifdef PIN_MEM_REF
                        newTime();
#endif
                    }
                    delete retList;
                    node->value.vpoint = nullptr;
#ifdef PIN_MEM_REF
                    newTime();
#endif
                }

            }
            }
            else
            {
                //自然返回，没有遇到fanhui语句。即不需要返回什么值。
                std::list<std::string>* pRetList = pFunInfo->retList;
                //如果函数有返回参数，则必须要通过fanhui返回。
                if (pRetList != nullptr)
                {
                    //参数和值不能匹配
                    QString errmsg = QString(u8"错误：函数 %1 体没有返回值,该函数形式需要返回值 ！").arg(QString::fromStdString(name));
                    AbortException(errmsg);
                    return 0;
                }
            }

            deleteCurFunction();

        }

	return 0;
}
#endif

//除法
std::any ExprVisitor::visitDivExpr(PinParser::DivExprContext *ctx)
{
    ExprValue ret;
    ret.type = EXPR_ERR;

    //除法，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr(0)->getText();

    //int leftType = getVarTypeByName(lefttext);
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr(0)));

    std::string righttext = ctx->expr(1)->getText();
    ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->expr(1)));

    //如果相等，直接相乘
    if(leftExpr.type == rightExpr.type)
    {
        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            if (rightExpr.value.vint == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint = leftExpr.value.vint / rightExpr.value.vint;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            if (rightExpr.value.vint64 == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint64 = leftExpr.value.vint64 / rightExpr.value.vint64;
            break;
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat / rightExpr.value.vfloat;
            break;
        case EXPR_STRING:
            //字符串无法相乘，报告异常
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 字符串无法做除法！").arg(curLine).arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
        return ret;
    }
    else
    {
        int type  = leftExpr.type << 16 | rightExpr.type;

        switch(type)
        {
        case EXPR_INT << 16 | EXPR_INT64:
            ret.type = EXPR_INT;
            if (rightExpr.value.vint64 == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint = leftExpr.value.vint / rightExpr.value.vint64;
            break;
        case EXPR_INT << 16 | EXPR_FLOAT:
            //优先返回高精度的小数。
            ret.type = EXPR_FLOAT;
            ret.value.vfloat =  double(leftExpr.value.vint) / rightExpr.value.vfloat;
            break;
        case EXPR_INT64 << 16 | EXPR_INT:
            ret.type = EXPR_INT64;
            if (rightExpr.value.vint == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint64 = leftExpr.value.vint64 / rightExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = double(leftExpr.value.vint64) / rightExpr.value.vfloat;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT:
            ret.type = EXPR_FLOAT;
            if (rightExpr.value.vint == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vfloat = leftExpr.value.vfloat / rightExpr.value.vint;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT64:
            ret.type = EXPR_FLOAT;
            if (rightExpr.value.vint64 == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 除数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vfloat = leftExpr.value.vfloat / rightExpr.value.vint64;
            break;
        default:
            QString errmsg = QString(u8"错误语句 %1 表达式无法做除法！请检查含有不能做除法的语句，比如字符串。").arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
    }
    return ret;
}


//乘法表达式
std::any ExprVisitor::visitMultExpr(PinParser::MultExprContext *ctx)
{

    ExprValue ret;
    ret.type = EXPR_ERR;

    //乘法，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr(0)->getText();

    //int leftType = getVarTypeByName(lefttext);
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr(0)));

    std::string righttext = ctx->expr(1)->getText();
    ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->expr(1)));

    //如果相等，直接相乘
    if(leftExpr.type == rightExpr.type)
    {
        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint * rightExpr.value.vint;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 * rightExpr.value.vint64;
            break;
        /*case EXPR_DOUBLE:
            ret.type = EXPR_DOUBLE;
            ret.value.vdouble = leftExpr.value.vdouble * rightExpr.value.vdouble;
            break;*/
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat * rightExpr.value.vfloat;
            break;
        case EXPR_STRING:
            //字符串无法相乘，报告异常
            QString errmsg = QString(u8"错误语句 %1 字符串无法做乘法！").arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
        return ret;
    }
    else
    {
        int type  = leftExpr.type << 16 | rightExpr.type;

        switch(type)
        {
        case EXPR_INT << 16 | EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = rightExpr.value.vint64 * leftExpr.value.vint;
            break;
        case EXPR_INT << 16 | EXPR_FLOAT:
            //优先返回小数
            ret.type = EXPR_FLOAT;
            ret.value.vfloat =  rightExpr.value.vfloat * leftExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_INT:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 * rightExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = rightExpr.value.vfloat * leftExpr.value.vint64;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat * rightExpr.value.vint;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT64:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat * rightExpr.value.vint64;
            break;
        default:
            QString errmsg = QString(u8"错误语句 %1 表达式无法做乘法！请检查含有不能做乘法的语句，比如字符串。").arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
    }


    return ret;
}

//余数表达式
std::any ExprVisitor::visitRemainderExpr(PinParser::RemainderExprContext* ctx)
{
    ExprValue ret;
    ret.type = EXPR_ERR;

    //乘法，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr(0)->getText();

    //int leftType = getVarTypeByName(lefttext);
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr(0)));

    std::string righttext = ctx->expr(1)->getText();
    ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->expr(1)));

    //如果相等，直接相乘
    if (leftExpr.type == rightExpr.type)
    {
        switch (leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            if (rightExpr.value.vint == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint = leftExpr.value.vint % rightExpr.value.vint;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            if (rightExpr.value.vint64 == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint64 = leftExpr.value.vint64 % rightExpr.value.vint64;
            break;
        case EXPR_FLOAT:
        {
            QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数求值时余数值只能是整数，不能是小数").arg(curLine).arg(curStatement);
            AbortException(errmsg);

        }
            break;
        case EXPR_STRING:
            //字符串无法相乘，报告异常
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 字符串无法做除法！").arg(curLine).arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
        return ret;
    }
    else
    {
        int type = leftExpr.type << 16 | rightExpr.type;

        switch (type)
        {
        case EXPR_INT << 16 | EXPR_INT64:
            ret.type = EXPR_INT;
            if (rightExpr.value.vint64 == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint = leftExpr.value.vint % rightExpr.value.vint64;
            break;
        case EXPR_INT << 16 | EXPR_FLOAT:
        {
            QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数求值时余数值只能是整数，不能是小数").arg(curLine).arg(curStatement);
            AbortException(errmsg);

        }
            break;
        case EXPR_INT64 << 16 | EXPR_INT:
            ret.type = EXPR_INT64;
            if (rightExpr.value.vint == 0)
            {
                QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数表达式值是0，发生除0错误，请检查 ！").arg(curLine).arg(curStatement);
                AbortException(errmsg);
            }
            ret.value.vint64 = leftExpr.value.vint64 % rightExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_FLOAT:
        {
            QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数求值时余数值只能是整数，不能是小数").arg(curLine).arg(curStatement);
            AbortException(errmsg);

        }
            break;
        case EXPR_FLOAT << 16 | EXPR_INT:
        case EXPR_FLOAT << 16 | EXPR_INT64 :
        {
            QString errmsg = QString(u8"错误: 行号 %1 语句 %2 余数求值时被余数值只能是整数，不能是小数").arg(curLine).arg(curStatement);
            AbortException(errmsg);

        }

        default:
            QString errmsg = QString(u8"错误语句 %1 表达式无法做余法！请检查含有不能做余法的语句，比如字符串。").arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
    }

    return ret;
}

//flag64 是否无条件按64位去取，默认false
//遇到纯数字时，有时候不清楚是否会越界，可指定flag64 true统一按64位去取。
ExprValue getIntFromText(std::string text, bool flag64 = false)
{
    qint64 value = 0;

    if(text.substr(0, 2) == "0x" || text.substr(0, 2) == "0X")
    {
        value = std::stoll(text, nullptr, 16);
    }
    else
    {
        value = std::stoll(text);
    }


    ExprValue ret;
/*
    if (flag64)
    {
        ret.type = EXPR_INT64;
        ret.value.vint64 = value;
        return ret;
    }
    */
/*
    qint64 highPart = (value >> 32) & 0xFFFFFFFF;  // 取高 32 位


    //等于0，说明int够了
    if (highPart == 0)
    {
        ret.type = EXPR_INT;
        ret.value.vint = static_cast<qint32>(value);  // 提取低 32 位
    }
    else
    {
        ret.type = EXPR_INT64;
        ret.value.vint64 = value;
    }*/

    // 直接判断 value 是否在 qint32 的范围内
       if (value >= std::numeric_limits<qint32>::min() && value <= std::numeric_limits<qint32>::max()) {
           ret.type = EXPR_INT;
           ret.value.vint = static_cast<qint32>(value);
       } else {
           ret.type = EXPR_INT64;
           ret.value.vint64 = value;
       }

    return ret;
}

//访问整数。但是要看整数的范围, 是 int 还是 int64
std::any ExprVisitor::visitIntExpr(PinParser::IntExprContext *ctx) {

    return getIntFromText(ctx->getText());
}




std::any ExprVisitor::visitCharValueExpr(PinParser::CharValueExprContext *ctx)  {
    //std::cout << "--- visitCharValueExpr" << ctx->getText() << std::endl;
     ExprValue ret;
     ret.type = EXPR_CHAR;

     std::string text = ctx->getText();
     const char* pChar = text.data();
     if(text.size() == 3 && pChar[0] == '\'')
     {
         ret.value.vchar = pChar[1];
     }
     else if(text.size() == 4 && pChar[0] == '\''&& pChar[1] == '\\') //是 \n \r类似的转义字符
     {
         switch (pChar[2])
         {
         case 't':
             ret.value.vchar = '\t';

             break;
         case 'r':
             ret.value.vchar = ('\r');

             break;
         case 'n':
             ret.value.vchar = ('\n');

             break;
         case 'b':
             ret.value.vchar = ('\b');

             break;
             //不要\f，发现打印出来乱码。
         //case 'f':
         //	dst.append('\f');
         //	++i;
         //	break;
         case '"':
             ret.value.vchar = '\"';

             break;
         case '\'':
             ret.value.vchar = '\'';
         default:
             QString msg = QString(u8"错误：行号 %1 语句 %2 非法的转义字符类型，转义支持 \\t \\r \\n \\b \\\" \\' ,其余不支持！").arg(curLine).arg(curStatement);
             AbortException(msg);
             break;
         }

     }
     else if(text.size() >= 5 && text.size() <= 6)
     {
            if(pChar[1] == '0' && (pChar[2] == 'x' || pChar[2] == 'X'))
            {
                long num = std::stoi(text, NULL, 16);  // 跳过 '0x00' '0x1' 格式
                ret.value.vchar =  (char)num;
            }
            else
            {
                //看看是不是宽字符的汉字。
                QString qstr = QString::fromStdString(text);
                //是类似'我'这样的汉字。
                if(qstr.size() == 3)
                {
                    ret.type = EXPR_WCHAR;
                    ret.value.vwchar = qstr.at(1).unicode();
                }
                else
                {
                    ret.type = EXPR_ERR;
                }
            }
     }
     else
     {
             QString msg = QString(u8"错误：行号 %1 语句 %2 非法的字符类型，字符格式需要是单字符'c'或16进制 0xff 格式！").arg(curLine).arg(curStatement);
             AbortException(msg);
    }

     return ret;
}

#if 0
std::any ExprVisitor::visitVarExpr(PinParser::VarExprContext *ctx)
{
    std::string name = ctx->getText();

    //如果是结构体变量,要以结构体的方式来求值。
    if(ctx->pinvar()->structMem())
    {
        return visit(ctx->pinvar());
    }
    if(ctx->pinvar()->STRUCT_ID())
    {
        return visit(ctx->pinvar());
    }
    else if(ctx->pinvar()->accesslist())
    {
        return visit(ctx->pinvar());
    }
    else if(ctx->pinvar()->accessmap())
    {
        return visit(ctx->pinvar());
    }
    else if(ctx->pinvar()->FILE_ID())
    {
        return visit(ctx->pinvar());
    }
    /*
    else if(ctx->pinvar()->memberFunAccess())
    {
        PinParser::MemberFunAccessContext* pMemfun = ctx->pinvar()->memberFunAccess();
        //成员函数访问
        ExprValue ret;
        ret.type = EXPR_MEMFUN;
        MEM_FUN_INFO* pData = new MEM_FUN_INFO(pMemfun->funobj()->getText(),pMemfun->OBJ_FUN_NAME()->getText());
#ifdef PIN_MEM_REF
            newTime();
#endif
        ret.value.vpoint = pData;
        return ret;
    }
    else if(ctx->pinvar()->CUSTOM_FUN_NAME())
    {
        //普通函数访问
        ExprValue ret;
        ret.type = EXPR_FUN;
        ret.value.vpoint = new std::string(ctx->pinvar()->CUSTOM_FUN_NAME()->getText());
#ifdef PIN_MEM_REF
            newTime();
#endif
        return ret;
    }
    */


    SymNode* pSym = getVarFromSymTable(name, ctx);

    ExprValue ret;

    if(pSym == nullptr){

        QString msg = QString(u8"函数 %1 语句 %2 中存在未定义的变量 %3").arg(QString::fromStdString(ctx->getText())).arg(QString::fromStdString(getCurFunName())).arg(QString::fromStdString(name));

        AbortException(msg);

        ret.type = EXPR_ERR;
    }else
    {
        ret.type = pSym->type;

        FillExprBySymNode(&ret,pSym,ctx);

        //后面记住，不能使用ret.value.vint64 = pSym->value.vint64，这样其实int int64会有差别。
        /*
        //这里坑，如果是字符串，还需要深拷贝，否则有问题。
        if(ret.type == EXPR_STRING)
        {
            ret.value.vpoint = new QByteArray(*(QByteArray*)pSym->value.vpoint);
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            ret.value.vint64 = pSym->value.vint64; //按最大的走。
        }
        */
    }

    return ret;
}
#endif

#if 0
std::any ExprVisitor::visitAutoSubExpr(PinParser::AutoSubExprContext *ctx)  {
    ExprValue ret;
    ret.type = EXPR_ERR;

    //加分，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr()->getText();
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr()));


        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint - 1;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 - 1;
            break;
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat - 1;
            break;

        default:
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 表达式减一,只有整数或小数才能做减一操作").arg(curLine).arg(curStatement);
            AbortException(errmsg);

            break;
        }


    return ret;
}

std::any ExprVisitor::visitAutoAddExpr(PinParser::AutoAddExprContext *ctx) {

    ExprValue ret;
    ret.type = EXPR_ERR;

    //加分，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr()->getText();
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr()));


        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint + 1;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 + 1;
            break;
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat + 1;
            break;

        default:
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 表达式加一,只有整数或小数才能做加一操作").arg(curLine).arg(curStatement);
            AbortException(errmsg);

            break;
        }


    return ret;
}
#endif

std::any ExprVisitor::visitPinAutoAddSub(PinParser::PinAutoAddSubContext *ctx)
{
    ExprValue varExpr = std::any_cast<ExprValue>(visitPinvar(ctx->pinvar(),true));
    if(!(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64 || varExpr.type == EXPR_FLOAT))
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 %3类型不是数值，只有整数或小数才能使用 ++ --,请检查！").arg(curLine).arg(curStatement).arg(QStr(ctx->pinvar()->getText()));
        AbortException(msg);
    }

    //这里不用减引用，因为只能是数值，都是直接值拷贝。

    //把++ 或 -- 转换为 += 1 -=1 编写执行

    std::string oper = ctx->AUTO_ADD_SUB()->getText();
    const char* rawPtr = oper.data();

    if(rawPtr[0] == '+')
    {
        //size_t pos = s.find("++");
        //s.replace(pos, 2, "+=1");
        if(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64)
        {
            ++varExpr.value.vint64;
        }
        else
        {
            ++varExpr.value.vfloat;
        }

    }
    else
    {
        //size_t pos = s.find("--");
        //s.replace(pos, 2, "-=1");
        if(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64)
        {
            --varExpr.value.vint64;
        }
        else
        {
            --varExpr.value.vfloat;
        }
    }

    visitPinvar(ctx->pinvar(),false,&varExpr);

    return varExpr;
}

#if 0
//a++ a--自动赋值。
std::any ExprVisitor::visitAssignAutoAdd(PinParser::AssignAutoAddContext *ctx)
{
    std::string s = ctx->getText();

   // std::cout << "---visitAssignAutoAdd" << ctx->pinvar()->getText() << std::endl;


    ExprValue varExpr = std::any_cast<ExprValue>(visitPinvar(ctx->pinvar(),true));
    if(!(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64 || varExpr.type == EXPR_FLOAT))
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 %3类型不是数值，只有整数或小数才能使用 ++ --,请检查！").arg(curLine).arg(curStatement).arg(QStr(ctx->pinvar()->getText()));
        AbortException(msg);
    }

    //这里不用减引用，因为只能是数值，都是直接值拷贝。

    //把++ 或 -- 转换为 += 1 -=1 编写执行

    if(ctx->AUTO_ADD_SUB()->getText() == "++")
    {
        //size_t pos = s.find("++");
        //s.replace(pos, 2, "+=1");
        if(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64)
        {
            ++varExpr.value.vint64;
        }
        else
        {
            ++varExpr.value.vfloat;
        }

    }
    else if(ctx->AUTO_ADD_SUB()->getText() == "--")
    {
        //size_t pos = s.find("--");
        //s.replace(pos, 2, "-=1");
        if(varExpr.type == EXPR_INT || varExpr.type == EXPR_INT64)
        {
            varExpr.value.vint64;
        }
        else
        {
            varExpr.value.vfloat;
        }
    }

    visitPinvar(ctx->pinvar(),false,&varExpr);

    return varExpr;

#if 0
    //执行真正的函数调用语句
    antlr4::ANTLRInputStream bodyStream(s);

    PinLexer lexer(&bodyStream);

    CommonTokenStream tokens(&lexer);

    PinParser parser(&tokens);
    PinErrListener errListener;
    errListener.tokens = &tokens;

    parser.removeErrorListeners();
    parser.addErrorListener(&errListener);

    tree::ParseTree* tree = parser.assignOne();

    //这里还是有些问题，发现 hs_callback(zs_1) 后面没有;号，走realCallFun时，居然没法走，真是奇怪，可能哪里有bug。还是优先匹配了callFun
    //但是现在callFun必须要带一个；号，call_back函数现在没法直接执行。

    ExprVisitor expr;
    expr.visit(tree);
    return 0;
#endif

}
#endif


//加法表达式
std::any ExprVisitor::visitAddExpr(PinParser::AddExprContext *ctx)
{

    ExprValue ret;
    ret.type = EXPR_ERR;

    //加分，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr(0)->getText();
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr(0)));

    std::string righttext = ctx->expr(1)->getText();
    ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->expr(1)));

    //如果相等，直接相加
    if(leftExpr.type == rightExpr.type)
    {
        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint + rightExpr.value.vint;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 + rightExpr.value.vint64;
            break;
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat + rightExpr.value.vfloat;
            break;
        case EXPR_STRING:
            //字符串相加
            ret.type = EXPR_STRING;
            QByteArray* bytes = (QByteArray*)leftExpr.value.vpoint;
            bytes->append(*(QByteArray*)rightExpr.value.vpoint);


            ret.value.vpoint = bytes;

            //把表达式的内存清空。左边转移了，只需要释放右边
            leftExpr.value.vpoint = nullptr;
            rightExpr.freeMem();
            break;
        }
        return ret;
    }
    else
    {
        int type  = leftExpr.type << 16 | rightExpr.type;

        switch(type)
        {
        case EXPR_INT << 16 | EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = rightExpr.value.vint64 + leftExpr.value.vint;
            break;
        case EXPR_INT << 16 | EXPR_FLOAT:
            //优先返回小数
            ret.type = EXPR_FLOAT;
            ret.value.vfloat =  rightExpr.value.vfloat + leftExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_INT:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 + rightExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_FLOAT:
            ret.type = EXPR_FLOAT; //优先返回小数，避免丢失精度
            ret.value.vfloat = rightExpr.value.vfloat + leftExpr.value.vint64;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat + rightExpr.value.vint;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT64:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat + rightExpr.value.vint64;
            break;
        case EXPR_CHAR << 16 | EXPR_INT:
            ret.type = EXPR_CHAR;
            ret.value.vchar = leftExpr.value.vchar + rightExpr.value.vint;
            break;
        case EXPR_WCHAR << 16 | EXPR_INT:
            ret.type = EXPR_WCHAR;
            ret.value.vwchar = leftExpr.value.vwchar + rightExpr.value.vint;
            break;
        case EXPR_CHAR << 16 | EXPR_STRING:
        {
            ret.type = EXPR_STRING;
            QByteArray* pRet = new QByteArray();
#ifdef PIN_MEM_REF
            newTime();
#endif
            pRet->append(leftExpr.value.vchar);
            pRet->append(*(QByteArray*)rightExpr.value.vpoint);
            rightExpr.freeMem();

            ret.value.vpoint = pRet;
        }
            break;
        case EXPR_STRING  << 16 | EXPR_CHAR:
        {
            ret.type = EXPR_STRING;
            QByteArray* pRet = (QByteArray*)leftExpr.value.vpoint;
            pRet->append(rightExpr.value.vchar);
            leftExpr.value.vpoint = nullptr;
            ret.value.vpoint = pRet;
        }
        break;
        default:
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 表达式无法做加法！请检查含有不能做加法的组合，比如字符串+数字。").arg(curLine).arg(QString::fromStdString(ctx->getText()));
            std::exception_ptr eptr = std::make_exception_ptr(std::runtime_error(errmsg.toStdString()));

            std::rethrow_exception(eptr);

            break;
        }
    }


    return ret;
}


std::any ExprVisitor::visitSubExpr(PinParser::SubExprContext *ctx)
{

    ExprValue ret;
    ret.type = EXPR_ERR;

    //加分，只能是整数和整数
    //小数和整数，小数和小数
    std::string lefttext = ctx->expr(0)->getText();
    ExprValue leftExpr = std::any_cast<ExprValue>(visit(ctx->expr(0)));

    std::string righttext = ctx->expr(1)->getText();
    ExprValue rightExpr = std::any_cast<ExprValue>(visit(ctx->expr(1)));

    //如果相等，直接减法
    if(leftExpr.type == rightExpr.type)
    {
        switch(leftExpr.type)
        {
        case EXPR_INT:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint - rightExpr.value.vint;
            break;
        case EXPR_INT64:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 - rightExpr.value.vint64;
            break;
        case EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat - rightExpr.value.vfloat;
            break;
        case EXPR_STRING:
        {
            //字符串相加
            leftExpr.freeMem();
            rightExpr.freeMem();

            QString errmsg = QString(u8"错误:行号 %1 语句 %2 表达式无法做减法！请检查含有不能做减法的组合，比如字符串-数字。").arg(curLine).arg(curStatement);
            AbortException(errmsg);
        }
            break;
        case EXPR_CHAR:
        {
            //字符相减去
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vchar - rightExpr.value.vchar;

        }
        break;
        case EXPR_WCHAR:
        {
            //字符相减去
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vwchar - rightExpr.value.vwchar;
        }
            break;
    }
        return ret;
    }
    else
    {
        int type  = leftExpr.type << 16 | rightExpr.type;

        switch(type)
        {
        case EXPR_INT << 16 | EXPR_INT64:
            ret.type = EXPR_INT;
            ret.value.vint = leftExpr.value.vint - rightExpr.value.vint64;
            break;
        case EXPR_INT << 16 | EXPR_FLOAT:
            //优先返小数
            ret.type = EXPR_FLOAT;
            ret.value.vfloat =  (double)leftExpr.value.vint - rightExpr.value.vfloat;
            break;
        case EXPR_INT64 << 16 | EXPR_INT:
            ret.type = EXPR_INT64;
            ret.value.vint64 = leftExpr.value.vint64 - rightExpr.value.vint;
            break;
        case EXPR_INT64 << 16 | EXPR_FLOAT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = (double)leftExpr.value.vint64 - rightExpr.value.vfloat;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat - rightExpr.value.vint;
            break;
        case EXPR_FLOAT << 16 | EXPR_INT64:
            ret.type = EXPR_FLOAT;
            ret.value.vfloat = leftExpr.value.vfloat - rightExpr.value.vint64;
            break;
        case EXPR_CHAR << 16 | EXPR_INT:
            ret.type = EXPR_CHAR;
            ret.value.vchar = leftExpr.value.vchar - rightExpr.value.vint;
            break;
        case EXPR_WCHAR << 16 | EXPR_INT:
            ret.type = EXPR_WCHAR;
            ret.value.vwchar = leftExpr.value.vwchar - rightExpr.value.vint;
            break;
        default:
            QString errmsg = QString(u8"错误:行号 %1 语句 %2 表达式无法做加法！请检查含有不能做加法的组合，比如字符串+数字。").arg(curLine).arg(QString::fromStdString(ctx->getText()));
            AbortException(errmsg);

            break;
        }
    }


    return ret;
}

std::any ExprVisitor::visitFloatExpr(PinParser::FloatExprContext *ctx)
{
    double value = std::stod(ctx->getText());

    ExprValue ret;

    ret.type = EXPR_FLOAT;
    ret.value.vfloat = value;

    return ret;
}

std::any ExprVisitor::visitParenthesesExpr(PinParser::ParenthesesExprContext *ctx)
{
    return visit(ctx->expr());
}

//打印函数。直接返回字符串。
std::any ExprVisitor::visitFormat_string(PinParser::Format_stringContext *ctx)
{
    return ctx->STRING_VALUE()->getText();
}

std::any ExprVisitor::visitOutputExpr(PinParser::OutputExprContext *ctx)
{
#ifdef PIN_DEBUG
std::cout << u8"进入打印语句" << ctx->getText() <<  std::endl;
#endif

std::vector<PinParser::ExprContext *> exprVec = ctx->expr();

if(exprVec.size() > 0)
{
    //直接输出表达式
    // 访问每个表达式参数
    QList<ExprValue>args;
    for (auto e : exprVec) {

        ExprValue v = std::any_cast<ExprValue>(visit(e));
        args.append(v);
    }

    // 使用 QString 的 arg 方法进行格式化
    QString output;
    for (int i = 0, c = args.size(); i < c; ++i) {
        output += args[i].toString();

        if(i != c-1)
        {
            output += " ";
        }

        //每个表达式都要释放。
        args[i].freeMem();
    }
    std::cout << output.toStdString();

    if(ctx->DA_YIN_KEY()->getText() == "dyh" || ctx->DA_YIN_KEY()->getText() == "println")
    {
        std::cout << std::endl;
}

}
return 0;
}

std::any ExprVisitor::visitPrintExpr(PinParser::PrintExprContext *ctx)
{
	#ifdef PIN_DEBUG
    std::cout << u8"进入打印语句" << ctx->getText() <<  std::endl;
	#endif

    std::vector<PinParser::ExprContext *> exprVec = ctx->expr();

    if(exprVec.size() > 0)
    {
        //直接输出表达式
        // 访问每个表达式参数
        QList<ExprValue>args;
        for (auto e : exprVec) {

            ExprValue v = std::any_cast<ExprValue>(visit(e));
            args.append(v);
        }

        // 使用 QString 的 arg 方法进行格式化
        QString output;
        for (int i = 0, c = args.size(); i < c; ++i) {
            output += args[i].toString();

            //每个表达式都要释放。
            args[i].freeMem();

            if(i != c-1)
            {
                output += " ";
        }
    }
        std::cout << output.toStdString();

        if(ctx->DA_YIN_KEY()->getText() == "dyh" || ctx->DA_YIN_KEY()->getText() == "println")
        {
            std::cout << std::endl;
        }

    }
    return 0;
}

//字符串格式化操作。
std::any ExprVisitor::visitFmtString(PinParser::FmtStringContext* ctx)
{
    ExprValue ret;
    ret.type = EXPR_STRING;

    std::vector<PinParser::ExprContext*> exprVec;

    if (ctx->printFormatPart()->singleExpr() != nullptr)
    {
        exprVec.push_back(ctx->printFormatPart()->singleExpr()->expr());
    }
    else
    {
        exprVec = ctx->printFormatPart()->multiExpr()->expr();
    }

    std::string format = ctx->format_string()->getText();

    QByteArray qbytes = QByteArray::fromStdString(format);
    QByteArray escBytes = lexBytesToEscapeBytes(qbytes);


    QString msg = QString(escBytes);

    QList<QString> poslist;

    if (exprVec.size() > 0)
    {
        int pos = 0;
        int index = 0;

        for (int i = 0, c = exprVec.size(); i < c; ++i)
        {
            QString key = QString("%%1").arg(i + 1);
            index = msg.indexOf(key, pos);

            if (index != -1) {

                poslist.append(msg.mid(pos, index - pos));

                pos = index + key.size();
            }
            else
            {
                poslist.append(msg.mid(pos));
                pos = msg.size();
                break;
            }
        }

        //exprVec.size() 比格式化中%s要少
        if (pos < msg.size())
        {
            poslist.append(msg.mid(pos));
        }

        QList<ExprValue>args;
        for (auto e : exprVec) {

            ExprValue v = std::any_cast<ExprValue>(visit(e));
            args.append(v);
        }

        QString output;
        int es = exprVec.size();
        int i = 0;
        for (int c = poslist.size(); i < c; ++i)
        {
            output += poslist.at(i);

            //如果表达式比格式化多，则可能继续打印
            if (i < es)
            {
                output += args[i].toString();
            }
        }
        //容错：表达式比参数多，继续打印表达式的值
        for (; i < es; ++i)
        {
            output += " " + args[i].toString();
        }

        //std::cout << output.toStdString() << std::endl;

        for (auto e : args) {
            //务必是否掉。
            e.freeMem();
        }
        QByteArray bytes = output.toUtf8();
        ret.value.vpoint = new QByteArray(std::move(bytes));

#ifdef PIN_MEM_REF
        newTime();
#endif
    }
    else
    {
        std::cout << format << std::endl;

        QByteArray bytes = QByteArray::fromStdString(format);

        ret.value.vpoint = new QByteArray(std::move(bytes));

#ifdef PIN_MEM_REF
        newTime();
#endif
    }
    return ret;
}

std::any ExprVisitor::visitFormatPrintExpr(PinParser::FormatPrintExprContext *ctx)
{
	#ifdef PIN_DEBUG
    std::cout << u8"进入格式化打印语句" << ctx->getText() <<  std::endl;
	#endif

    ExprValue ret = std::any_cast<ExprValue>(visit(ctx->fmtString()));

    std::cout << ((QByteArray*)ret.value.vpoint)->toStdString();

    if(ctx->DA_YIN_KEY()->getText() == "dyh" || ctx->DA_YIN_KEY()->getText() == "println")
    {
        std::cout << std::endl;
    }

    ret.freeMem();

#if 0
    std::vector<PinParser::ExprContext *> exprVec = ctx->fmtString()->printFormatPart()->expr();

    std::string format = ctx->fmtString()->format_string()->getText();

    QByteArray qbytes = QByteArray::fromStdString(format);
    QByteArray escBytes = lexBytesToEscapeBytes(qbytes);


    QString msg = QString(escBytes);

    QList<QString> poslist;

    if(exprVec.size() > 0)
    {
        int pos = 0;
        int index = 0;

        for(int i=0, c = exprVec.size(); i < c; ++i)
        {
            QString key = QString("%%1").arg(i+1);
            index = msg.indexOf(key,pos);

            if(index != -1){

                poslist.append(msg.mid(pos,index - pos));

                pos = index + key.size();
            }
            else
            {
                poslist.append(msg.mid(pos));
                pos = msg.size();
                break;
            }
        }

        //exprVec.size() 比格式化中%s要少
        if(pos < msg.size())
        {
             poslist.append(msg.mid(pos));
        }

        QList<ExprValue>args;
        for (auto e : exprVec) {

            ExprValue v = std::any_cast<ExprValue>(visit(e));
            args.append(v);
        }

        QString output;
        int es = exprVec.size();
        int i = 0;
        for(int c= poslist.size(); i < c; ++i)
        {
            output += poslist.at(i);

            //如果表达式比格式化多，则可能继续打印
            if(i < es)
            {
                output += args[i].toString();
            }
        }
        //容错：表达式比参数多，继续打印表达式的值
        for(;i < es;++i)
        {
            output += " " + args[i].toString();
        }

        std::cout << output.toStdString() << std::endl;


        for (auto e : args) {
            //务必是否掉
            e.freeMem();
        }
    }
    else
    {
        std::cout << format << std::endl;
    }
#endif
    return 0;
}



//函数返回
std::any ExprVisitor::visitRetCode(PinParser::RetCodeContext* ctx) 
{
    std::vector<PinParser::RightvarContext *> retVec = ctx->rightvar();

    //std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    if (retVec.size() == 0)
    {
        //直接返回的,没有返回结果。即fanhui 形式
        if (nullptr == curFunRetPara())
        {
            setcurFunReturnValue(nullptr);
        }
        else
        {
            //std::string funName;
            //std::list<std::string>* retArgs = curFunRetPara(&funName);
            //返回参数不符合
            QString msg = QString(u8"错误：函数 %1 语句 %2 实际返回的值和函数定义形式不匹配！").arg(getCurFunQSName()).arg(QString::fromStdString(ctx->getText()));

            AbortException(msg);
        }
    }
    else
    {
        std::string funName;
        std::vector<std::string>* retArgs = curFunRetPara(&funName);

        if (retArgs == nullptr)
        {
            QString msg = QString(u8"错误：函数 %1 没有定义返回值,函数实际返回的值和函数定义形式不匹配！").arg(QString::fromStdString(funName));
            AbortException(msg);
            return 0;
        }

        //访问每个参数表达式
        std::vector<std::string>::iterator it = retArgs->begin();

        bool isNeedRet = isFunNeedReturnValue();

        QList<SymNode*>* paraSymList = isNeedRet ? new QList<SymNode*>() : nullptr;

#ifdef PIN_MEM_REF
        if(isNeedRet)
        {
        newTime();
        }
#endif
        //参数个数不一样
        if (retArgs->size() != retVec.size())
        {
            QString msg = QString(u8"错误：函数 %1 中语句 %2 实际返回的值和函数定义形式不匹配！").arg(QString::fromStdString(funName)).arg(QString::fromStdString(ctx->getText()));
            AbortException(msg);
            return 0;
        }
        //进一步求解表达式
        for (auto e : retVec)
        {
            ExprValue expr = std::any_cast<ExprValue>(visit(e));
            int paraType = getVarTypeByName(*it);

            SymNode* newVar = new SymNode();

#ifdef PIN_MEM_REF
            newTime();
#endif
            newVar->name = *it;
            newVar->type = paraType;

            if (FillSymNodeByExpr(newVar, expr, ctx, true) >= 0)
            {
                //定义一个新的形参栈变量，把变量入栈
                //定义变量
                 expr.freeMem();
                if (isNeedRet)
                {

                    paraSymList->append(newVar);
                }
                else
                {
                    newVar->destory();
                    delete newVar;
#ifdef PIN_MEM_REF
        freeTimes++;
#endif
                }

            }
            else
            {
                //参数和值不能匹配
                QString errmsg = QString(u8"函数 %1 返回的参数值 %1 与 函数定义中的变量 %2 类型不匹配！").arg(QString::fromStdString(funName)).arg(expr.toString()).arg(QString::fromStdString(newVar->name));
                AbortException(errmsg);
                return 0;
            }
            ++it;
        }
        //不需要的，自然填充为nullptr
        //返回值填充
        setcurFunReturnValue(paraSymList);
    }
    //进入函数返回模式。一旦进入该模式，后续语句不再执行。
    pushStatus(FUNCTION_RET);
    return 0;
}


std::any ExprVisitor::visitIf(PinParser::IfContext* ctx)
{
    PinParser::ExprContext* pExpr = ctx->expr();
    if (pExpr != nullptr)
    {
        ExprValue value = std::any_cast<ExprValue>(visit(pExpr));
        if (value.type == EXPR_BOOL)
        {
            //value.freeMem();
            //表达式为真，执行后续表达式
            if (value.value.vbool)
            {
               if (nullptr != ctx->statement())
                {

                   if (nullptr != ctx->statement()->block())
                   {
                       visit(ctx->statement()->block());
                }
                else
                {
                    addNewScope();

                    //加入一个作用域。单句语句if访问
                    visit(ctx->statement());

                    deleteCurScope();
                   }
                }
                else
                {
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2，if 缺少表达式对应的块执行代码 ！").arg(curLine)
                        .arg(QString::fromStdString(ctx->getText()));

                    AbortException(errmsg);
                }
            }
            else
            {
                //执行后续的表达式
                //如果存在zif，先执行zif

                bool isIfExed = false;

                std::vector<PinParser::ZifContext*> zifVec = ctx->zif();
                if (zifVec.size() > 0)
                {
                    for (int i = 0, s = zifVec.size(); i < s; ++i)
                    {
                        PinParser::ZifContext* pZif = zifVec.at(i);

                        PinParser::ExprContext* pZifExpr = pZif->expr();
                        if (pZifExpr != nullptr)
                        {
                            ExprValue value = std::any_cast<ExprValue>(visit(pZifExpr));


                            //表达式为真，执行后续表达式
                            if (value.value.vbool)
                            {
                                value.freeMem();

                               /*if (nullptr != pZif->statement()->block())
                                {
                                    visit(pZif->statement()->block());
                                }*/
                                if (nullptr != pZif->statement())
                                 {

                                    if (nullptr != pZif->statement()->block())
                                    {
                                        visit(pZif->statement()->block());
                                }
                                else
                                {
                                     addNewScope();

                                     //加入一个作用域。单句语句if访问
                                     visit(pZif->statement());

                                     deleteCurScope();
                                    }
                                 }
                                else
                                {
                                    QString errmsg = QString(u8"错误：行号 %1 语句 %2，zif 缺少表达式对应的块执行代码 ！").arg(curLine)
                                        .arg(QString::fromStdString(pZif->getText()));

                                    AbortException(errmsg);
                                }
                                //执行完毕以后，不在执行后续的语句。
                                isIfExed = true;
                                break;
                            }

                        }
                        else
                        {
                            QString errmsg = QString(u8"错误：行号 %1 语句 %2，zif 缺少表达式对应的块执行代码 ！").arg(curLine)
                                .arg(QString::fromStdString(pZif->getText()));

                            AbortException(errmsg);
                        }
                    }
                }

                //都没有执行，但是存在qt语句，执行
                if (!isIfExed && ctx->qt() != nullptr)
                {
                    PinParser::QtContext* pQt = ctx->qt();

                   /* if (nullptr != pQt->block())
                    {
                        visit(pQt->block());
                    }*/
                    if (nullptr != pQt->statement())
                     {

                        if (nullptr != pQt->statement()->block())
                        {
                            visit(pQt->statement()->block());
                    }
                    else
                    {
                         addNewScope();

                         //加入一个作用域。单句语句if访问
                         visit(pQt->statement());

                         deleteCurScope();
                        }
                     }
                    else
                    {
                        QString errmsg = QString(u8"错误：行号 %1 语句 %2，qt 缺少表达式对应的块执行代码 ！").arg(curLine)
                            .arg(QString::fromStdString(pQt->getText()));

                        AbortException(errmsg);
                    }
                }

            }
        }
        else
        {
            QString errmsg = QString(u8"错误：行号 %1 语句 %2，if 判断表达式不是布尔逻辑类型 ！").arg(curLine)
                .arg(QString::fromStdString(ctx->getText()));

            AbortException(errmsg);
        }
    }
    else
    {
        QString errmsg = QString(u8"错误：行号 %1 语句 %2，缺少if 布尔逻辑判定表达式 ！").arg(curLine)
            .arg(QString::fromStdString(ctx->getText()));

        AbortException(errmsg);
    }
    return 0;
}


//if 的 zif语句
std::any ExprVisitor::visitZif(PinParser::ZifContext* ctx)
{
    PinParser::ExprContext* pExpr = ctx->expr();
    if (pExpr != nullptr)
    {
        ExprValue value = std::any_cast<ExprValue>(visit(pExpr));
        if (value.type == EXPR_BOOL)
        {
            //表达式为真，执行后续表达式
            if (value.value.vbool)
            {
                /*
                if (nullptr != ctx->block())
                {
                    visit(ctx->block());
                }*/
                if (nullptr != ctx->statement())
                 {

                    if (nullptr != ctx->statement()->block())
                    {
                        visit(ctx->statement()->block());
                }
                else
                {
                     addNewScope();

                     //加入一个作用域。单句语句if访问
                     visit(ctx->statement());

                     deleteCurScope();
                    }
                 }
                else
                {
                    QString errmsg = QString(u8"错误：行号 %1 语句 %2，zif 缺少表达式对应的块执行代码 ！").arg(curLine)
                        .arg(QString::fromStdString(ctx->getText()));

                    AbortException(errmsg);
                }
            }
            value.freeMem();
        }
    }
    else
    {
        QString errmsg = QString(u8"错误：行号 %1 语句 %2，缺少zif 布尔逻辑判定表达式 ！").arg(curLine)
            .arg(QString::fromStdString(ctx->getText()));

        AbortException(errmsg);
    }
    return 0;
}

std::any ExprVisitor::visitQt(PinParser::QtContext* ctx)
{
    //表达式为真，执行后续表达式
    /*if (nullptr != ctx->block())
    {
        visit(ctx->block());
    }*/
    if (nullptr != ctx->statement())
     {

        if (nullptr != ctx->statement()->block())
        {
            visit(ctx->statement()->block());
    }
    else
    {
         addNewScope();

         //加入一个作用域。单句语句if访问
         visit(ctx->statement());

         deleteCurScope();
        }
     }
    else
    {
        QString errmsg = QString(u8"错误：行号 %1 语句 %2，qt 缺少表达式对应的块执行代码 ！").arg(curLine)
            .arg(QString::fromStdString(ctx->getText()));

        AbortException(errmsg);
    }
    return 0;
}


//处理负号
std::any ExprVisitor::visitNegationExpr(PinParser::NegationExprContext* ctx)
{
	#ifdef PIN_DEBUG
    std::cout << u8"发现负号表达式" << ctx->getText();
	#endif

    PinParser::AtomContext* pAtom = ctx->atom();

    ExprValue ret;

    if (pAtom->INT_VALUE() != nullptr)
    {
        //纯数字，统一按64位去取，这样不会溢出，更加安全。
        //这里exprvalue 不用关心 字符串内存深拷贝问题，因为不是字符串。
        ret = getIntFromText(pAtom->INT_VALUE()->getText(),true);
        ret.value.vint64 = -ret.value.vint64;

    }
    else if (pAtom->FLOAT_VALUE() != nullptr)
    {
        double value = std::stod(pAtom->FLOAT_VALUE()->getText());
        ret.type = EXPR_FLOAT;
        ret.value.vfloat = -value;

    }
    else if(pAtom->pinvar() != nullptr)
    {
        ExprValue expr = std::any_cast<ExprValue>(visitPinvar(pAtom->pinvar(),true,nullptr));
        //必须是整数模式
        if(expr.type == EXPR_INT || expr.type == EXPR_INT64 || expr.type == EXPR_FLOAT)
        {
            ret.type = expr.type;
            FillExprByExpr(&ret, &expr,ctx,true,SUB_ASSIGN);
        }
        else
        {
            subListMapRefNum(expr);
        }
    }
    /*
    else if (pAtom->INT32() != nullptr)
    {
        std::string varName = pAtom->INT32()->getText();
        SymNode* pSym = getVarFromSymTable(varName, ctx);
        ret.type = EXPR_INT;

        ret.value.vint = -pSym->value.vint;
    }
    else if (pAtom->INT64() != nullptr)
    {
        std::string varName = pAtom->INT64()->getText();
        SymNode* pSym = getVarFromSymTable(varName, ctx);
        ret.type = EXPR_INT64;

        ret.value.vint64 = -pSym->value.vint64;
    }
    else if (pAtom->FLOAT() != nullptr)
    {
        std::string varName = pAtom->FLOAT()->getText();
        SymNode* pSym = getVarFromSymTable(varName, ctx);
        ret.type = EXPR_FLOAT;

        ret.value.vfloat = -pSym->value.vfloat;
    }
    */
    else
    {
        QString errmsg = QString(u8"错误：行号 %1 语句 %2 遇到非法的负号表达式！只有整数和小数表达式才能求负值！").arg(curLine)
            .arg(curStatement);

        AbortException(errmsg);
    }

    return ret;
}

std::any ExprVisitor::visitForState(PinParser::ForStateContext* ctx)
{
    //进入循环
//看到for时，加入一个作用域
//    SymNode* node = new SymNode;
//#ifdef PIN_MEM_REF
//    newTime();
//#endif
//    node->type = FOR_SCOPE;
//    //作用域反而是没有名称的。
//    getPinSymTable()->push_back(node);

    addNewScope(FOR_SCOPE);

    //for中如果有定义变量，则该变量是在新作用域之下的。
    PinParser::ForinitContext* pInit = ctx->forinit();
    if (pInit != nullptr && pInit->defvar() != nullptr)
    {
        //走定义语句
        visit(pInit->defvar());
    }
    else if (pInit != nullptr && pInit->assign() != nullptr)
    {
        //走赋值语句
        visit(pInit->assign());
    }
    //其余不用干什么。

        //判断条件语句
    PinParser::ExprContext* pExpr = ctx->expr();
    if (pExpr != nullptr)
    {
        int times = 0; //避免死循环
        while (true)
        {
            ExprValue v = std::any_cast<ExprValue>(visit(pExpr));
            if (v.type == EXPR_BOOL)
            {
                //为真，则执行循环块。
                if (v.value.vbool)
                {
                    if (ctx->statement()->block() != nullptr)
                    {
                        visit(ctx->statement()->block());
                    }
                    else
                    {
                        addNewScope();
                        visit(ctx->statement());
                        deleteCurScope();
                    }

                    //如果是从break中返回，则不继续循环了
                    if (getPinRunStatus() == INTO_BREAK)
                    {
                        popStatus();
                        break;
                    }

                    ++times;

                    //没1000次调用一下界面，避免卡死。
                    if (times > 1000)
                    {
                        QCoreApplication::processEvents();
                        times = 0;
                    }

                    if (getPinRunStatus() == INTO_CONTINUE)
                    {
                        //执行尾语句，别忘记了
                        popStatus();

                        visit(ctx->forinc());

                        continue;
                    }
                }
                else
                {
                    //条件不满足了，退出循环。
                    break;
                }

                //执行完毕后。
                //执行表达式2
                if (ctx->forinc() != nullptr)
                {
                    visit(ctx->forinc());
                }
                //执行完毕后。继续判定表达式，循环继续。
            }
            else
            {
                QString errmsg = QString(u8"错误：函数 %1 语句 %2，循环缺少条件判断逻辑表达式，或循环执行判断表达式不是逻辑表达式 ！").arg(QString::fromStdString(getCurFunName()))
                    .arg(QString::fromStdString(pExpr->getText()));
                AbortException(errmsg);
                break;
            }
        }
    }

    deleteCurForScope();

    return 0;
}

std::any ExprVisitor::visitWhileState(PinParser::WhileStateContext* ctx)
{
    //进入循环
//看到for时，加入一个作用域
//    SymNode* node = new SymNode;
//#ifdef PIN_MEM_REF
//    newTime();
//#endif
//    node->type = FOR_SCOPE;
//    //作用域反而是没有名称的。
//    getPinSymTable()->push_back(node);

    addNewScope(FOR_SCOPE);

        //判断条件语句
    PinParser::ExprContext* pExpr = ctx->expr();
    if (pExpr != nullptr)
    {
        int times = 0;

        while (true)
        {
            ExprValue v = std::any_cast<ExprValue>(visit(pExpr));
            if (v.type == EXPR_BOOL)
            {
                //为真，则执行循环块。
                if (v.value.vbool)
                {
                    if (ctx->statement()->block() != nullptr)
                    {
                        visit(ctx->statement()->block());
                    }
                    else
                    {
                        addNewScope();
                        visit(ctx->statement());
                        deleteCurScope();
                    }

                    ++times;
                    //没1000次调用一下界面，避免卡死。
                    if (times > 1000)
                    {
                        QCoreApplication::processEvents();
                        times = 0;
                    }

                    //如果是从break中返回，则不继续循环了
                    if (getPinRunStatus() == INTO_BREAK)
                    {
                        popStatus();
                        break;
                    }

                    if (getPinRunStatus() == INTO_CONTINUE)
                    {
                        //执行尾语句，别忘记了
                        popStatus();
                        continue;
                    }
                }
                else
                {
                    //条件不满足了，退出循环。
                    break;
                }
            }
            else
            {
                QString errmsg = QString(u8"错误：函数 %1 语句 %2，循环缺少条件判断逻辑表达式，或循环执行判断表达式不是逻辑表达式 ！").arg(QString::fromStdString(getCurFunName()))
                    .arg(QString::fromStdString(pExpr->getText()));
                AbortException(errmsg);
                break;
            }
        }
    }

    deleteCurForScope();

    return 0;
}

std::any ExprVisitor::visitForInState(PinParser::ForInStateContext* ctx)
{
    //进入循环

    //这里注意，要先访问后面的rightvar变量，再加入新作用域。
    //这样可以避免待遍历的右边变量和kv同名的问题。
    //这里是获取引用
    ExprValue expr = std::any_cast<ExprValue>(visit(ctx->rightvar()));
    if (expr.type != EXPR_LIST && expr.type != EXPR_MAP && expr.type != EXPR_STRUCT)
    {
        QString errmsg = QString(u8"错误：函数 %1 语句 %2 只有列表、字典、结构体可以做循环对象！变量或表达式 %3 类型是 %4").arg(QString::fromStdString(getCurFunName()))
            .arg(QStr(ctx->rightvar()->getText())).arg(getExpeTypeValue(expr.type,&expr));
        AbortException(errmsg);
        return 0;
    }

    //看到for时，加入一个作用域
    //    SymNode* node = new SymNode;
    //#ifdef PIN_MEM_REF
    //    newTime();
    //#endif
    //    node->type = FOR_SCOPE;
    //    //作用域反而是没有名称的。
    //    getPinSymTable()->push_back(node);

    addNewScope(FOR_SCOPE);

    std::vector<PinParser::ForinvarContext*> varVec = ctx->forinvar();

    SymNode* node1 = nullptr;
    SymNode* node2 = nullptr;

    if (varVec.at(0)->getText() != std::string("_"))
    {
        //在作用域上创建2个变量。如果是列表，则是index,value,如果是字典，则是key,value
        node1 = new SymNode;
#ifdef PIN_MEM_REF
        newTime();
#endif
        node1->name = varVec.at(0)->getText();
        getPinSymTable()->push_back(node1);
    }
    if (expr.type == EXPR_LIST && node1 != nullptr)
    {
        node1->type = EXPR_INT;
    }

    if (varVec.at(1)->getText() != std::string("_"))
    {
        node2 = new SymNode;
#ifdef PIN_MEM_REF
        newTime();
#endif
        node2->name = varVec.at(1)->getText();
        node2->type = EXPR_INT;
        getPinSymTable()->push_back(node2);
    }

    //开始遍历列表
    if (expr.type == EXPR_LIST)
    {
        std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)expr.value.vpoint;

        for (int i = 0, s = pList->size(); i < s; ++i)
        {
            if (node1 != nullptr)
            {
                node1->value.vint = i;
            }
            if (node2 != nullptr)
            {
                node2->destory();
                node2->type = pList->at(i)->type;

                //返回的v是一个副本，不能修改原始的值。
                ExprValue pCopyValue = pList->at(i)->deepCopy(true);

                FillSymNodeByExpr(node2, pCopyValue, ctx);
            }

            //开始执行循环块
            if (ctx->statement()->block() != nullptr)
            {
                visit(ctx->statement()->block());
            }
            else
            {
                addNewScope();
                visit(ctx->statement());
                deleteCurScope();
            }

            //如果是从break中返回，则不继续循环了
            if (getPinRunStatus() == INTO_BREAK)
            {
                popStatus();
                break;
            }

            if (getPinRunStatus() == INTO_CONTINUE)
            {
                popStatus();
                continue;
            }
        }
    }
    else if (expr.type == EXPR_MAP)
    {
        std::unordered_map<ExprValue, ExprValue*>* pMap = (std::unordered_map<ExprValue, ExprValue*>*)expr.value.vpoint;
        for (auto it = pMap->begin(); it != pMap->end(); ++it)
        {
            if (node1 != nullptr)
            {
                node1->destory();

                node1->type = it->first.type;

                ExprValue pCopyKey = (it->first).deepCopy();

                FillSymNodeByExpr(node1, pCopyKey,ctx);
            }
            if (node2 != nullptr)
            {
                node2->destory();
                node2->type = it->second->type;

                //返回的v是一个副本，不能修改原始的值。
                ExprValue pCopyValue = it->second->deepCopy(true);

                FillSymNodeByExpr(node2, pCopyValue, ctx);
            }

            //开始执行循环块
             //开始执行循环块
            if (ctx->statement()->block() != nullptr)
            {
                visit(ctx->statement()->block());
            }
            else
            {
                addNewScope();
                visit(ctx->statement());
                deleteCurScope();
            }

            //如果是从break中返回，则不继续循环了
            if (getPinRunStatus() == INTO_BREAK)
            {
                popStatus();
                break;
            }

            if (getPinRunStatus() == INTO_CONTINUE)
            {
                popStatus();
                continue;
            }
        }
    }

    else if (expr.type == EXPR_STRUCT)
    {
        if (node1 != nullptr)
        {
            node1->type = EXPR_INT;
        }

        STRUCT_VALUE_DATA* pSrc = (STRUCT_VALUE_DATA*)expr.value.vpoint;

        std::vector<ExprValue*>* pList = (std::vector<ExprValue*>*)pSrc->pValue;

        if(pList != nullptr)
        {
            SymNode* pStructDesc = getVarFromGlobalSymTable(pSrc->structType, ctx, 1);
            std::vector<std::string>* pParalist = (std::vector<std::string>*)pStructDesc->value.vpoint;
            if (pParalist != nullptr && pParalist->size() > 0)
            {
                node1->type = EXPR_STRING;
            }
            for(int i=0,c=pList->size(); i<c; ++i)
            {
                if (node1 != nullptr)
                {
                    node1->destory();
                    node1->value.vpoint = new QByteArray(QByteArray::fromStdString(pParalist->at(i)));
#ifdef PIN_MEM_REF
        newTime();
#endif
                }
                if (node2 != nullptr)
                {
                    node2->destory();
                    node2->type = pList->at(i)->type;

                    //返回的v是一个副本，不能修改原始的值。
                    ExprValue pCopyValue = pList->at(i)->deepCopy(true);

                    FillSymNodeByExpr(node2, pCopyValue, ctx);
                }

                //开始执行循环块
                 //开始执行循环块
                if (ctx->statement()->block() != nullptr)
                {
                    visit(ctx->statement()->block());
                }
                else
                {
                    addNewScope();
                    visit(ctx->statement());
                    deleteCurScope();
                }

                //如果是从break中返回，则不继续循环了
                if (getPinRunStatus() == INTO_BREAK)
                {
                    popStatus();
                    break;
                }

                if (getPinRunStatus() == INTO_CONTINUE)
                {
                    popStatus();
                    continue;
                }
            }
        }

    }

    expr.freeMem();
    deleteCurForScope();

    return 0;
}

#if 0
//把整个for当做一个作用域来对待。
std::any ExprVisitor::visitFor(PinParser::ForContext* ctx)
{
    //进入循环
    //看到for时，加入一个作用域
    SymNode* node = new SymNode;
	#ifdef PIN_MEM_REF
            newTime();
#endif
    node->type = FOR_SCOPE;
    //作用域反而是没有名称的。
    getPinSymTable()->push_back(node);

    //for中如果有定义变量，则该变量是在新作用域之下的。
    PinParser::ForinitContext* pInit = ctx->forinit();
    if (pInit != nullptr && pInit->defvar() != nullptr)
    {
        //走定义语句
        visit(pInit->defvar());
    }
    else if (pInit != nullptr && pInit->assign() != nullptr)
    {
        //走赋值语句
        visit(pInit->assign());
    }
    //其余不用干什么。

        //判断条件语句
        PinParser::ExprContext* pExpr = ctx->expr();
        if (pExpr != nullptr)
        {
            while (true)
            {
                ExprValue v = std::any_cast<ExprValue>(visit(pExpr));
                if (v.type == EXPR_BOOL)
                {
                    //为真，则执行循环块。
                    if (v.value.vbool)
                    {
                        visit(ctx->block());

                        //如果是从break中返回，则不继续循环了
                        if(getPinRunStatus() == INTO_BREAK)
                        {
                            popStatus();
                            break;
                        }

                        if(getPinRunStatus() == INTO_CONTINUE)
                        {
                            //执行尾语句，别忘记了
                            popStatus();

                            visit(ctx->forinc());

                            continue;
                        }
                    }
                    else
                    {
                        //条件不满足了，退出循环。
                        break;
                    }

                    //执行完毕后。
                    //执行表达式2
                    if (ctx->forinc() != nullptr)
                    {
                        visit(ctx->forinc());
                    }
                    //执行完毕后。继续判定表达式，循环继续。
                }
                else
                {
                    QString errmsg = QString(u8"错误：函数 %1 语句 %2，循环缺少条件判断逻辑表达式，或循环执行判断表达式不是逻辑表达式 ！").arg(QString::fromStdString(getCurFunName()))
                        .arg(QString::fromStdString(pExpr->getText()));
                    AbortException(errmsg);
                    break;
                }
            }
        }

        deleteCurForScope();

    return 0;
}
#endif

std::any ExprVisitor::visitBreak(PinParser::BreakContext* ctx)
{
    //如果是在for语句中，则进入break
    if(isInFor())
    {
        pushStatus(INTO_BREAK);
    }
    else
    {
        QString errmsg = QString(u8"行号 %1 语句 %2 退出语句不在循环中，忽略").arg(curLine).arg(curStatement);

        std::cout << errmsg.toStdString() << std::endl;
    }
    return 0;
}

std::any ExprVisitor::visitContinue(PinParser::ContinueContext* ctx)
{
    if(isInFor())
    {
        pushStatus(INTO_CONTINUE);
    }
    else
    {
        QString errmsg = QString(u8"函数 %1 继续 jixu 语句不在循环中，忽略").arg(QString::fromStdString(getCurFunName()));

        std::cout << errmsg.toStdString() << std::endl;
    }
    return 0;
}

//stName 结构的类型名称
int getMemIndexFromStruct(std::string stName, std::string paraName, antlr4::ParserRuleContext* ctx)
{
     SymNode* pSym = getVarFromGlobalSymTable(stName, ctx,1);
     std::vector<std::string>*  paraVec = (std::vector<std::string>*)pSym->value.vpoint;
     auto it = std::find(paraVec->begin(), paraVec->end(), paraName);

     if (it != paraVec->end()) {
         // 计算元素的位置索引
         size_t index = std::distance(paraVec->begin(), it);
         return index;
     }
     return -1;
}

std::any ExprVisitor::visitStMemVar(PinParser::StMemVarContext *ctx)
{
    std::string varName = ctx->VARNAME()->getText();
    //只能是基本变量
    SymNode* pSym = getVarFromSymTable(varName, ctx);
    ExprValue ret;
    switch (pSym->type) {
    case EXPR_INT:
    case EXPR_INT64:
    case EXPR_STRING:
    case EXPR_DATE:
    case EXPR_FILE:
    case EXPR_CHAR:
    case EXPR_BOOL:
    case EXPR_WCHAR:
    case EXPR_U16STRING:
    {

        ret.type = pSym->type;

        FillExprBySymNode(&ret,pSym,ctx);

        return ret;
    }

        break;
    default:
        QString err = QString(u8"错误：行号 %1 语句 %2 错误的结构体成员，结构体成员只能是基本变量（整数、小数、字符串、字符、文件、时间）!");
        AbortException(err);
        break;
    }

    return ret;
    /*
    if(ctx->FILE_ID() != nullptr)
    {
        std::string varName = ctx->FILE_ID()->getText();

        SymNode* pSym = getVarFromSymTable(varName, ctx);

        if(pSym)
        {
            ExprValue ret;
            ret.type = EXPR_FILE;

            //文件和列表一样，都是浅拷贝
            //ret.value.vpoint = pSym->value.vpoint;

            FillExprBySymNode(&ret,pSym,ctx);

            return ret;
        }
        return 0;
    }
    else
    {
        return visitChildren(ctx);
    }
    */
}

//结构体单独匹配一下。默认还是值获取方式。
std::any ExprVisitor::visitPinvar(PinParser::PinvarContext *ctx)
{
    return visitPinvar(ctx,false);
}

//结构体单独匹配一下。是否是引用获取方式。isRefGet 默认为false。//对于文件、列表、字典，无论如果都是引用方式。
//但是对于日期，字符串，默认是值获取。如果要获取变量的引用，则isRefGet为true。目前绝大部分都是值获取方式，只有一个地方
//那就是调用对象的内部cpp函数的时候，需要获取引用，因为调用函数要修改对象的原始值。使用引用方式调用时，要特别注意，否则可能导致原始值被修改或破坏。
//如果是引用获取的方式，该不该增加引用计数呢？如果加了，外部要释放，如果不加，外部不需要释放。为了简单起见，统一增加，对于文件、列表、字典，就算是引用获取，也增加一下计数。
//这里还是有坑，对于基本变量，比如整数，浮点，都是无条件副本返回，所以这里的引用返回，其实是不严谨的，基本变量整数、浮点，无法引用返回。只有日期，字符串、文件、列表、字典才能
//返回所谓的引用。
//assignExpr 如果不是空，即使用assignExpr语句给变量赋值;assignExpr表达式会被掏空。即直接赋值，反之外面二次需要获取变量赋值。
//bool onlyGetType 默认为false,只返回表达式的类型，不返回内容。再表达式类型检查判断中有用
std::any ExprVisitor::visitPinvar(PinParser::PinvarContext *ctx, bool isRefGet, ExprValue * assignExpr,AssignOpType op)
{
    std::string varName = ctx->VARNAME()->getText();

    std::vector<PinParser::ListindexContext *> listIndex = ctx->listindex();

    PinParser::StMemVarContext* pStMem = ctx->stMemVar();

    SymNode* pSym= getVarFromSymTable(varName,ctx);

    //先检查变量本身的类型
    switch (pSym->type) {
    case EXPR_STRING:
    case EXPR_U16STRING:
    {
        if( listIndex.size() == 0)
        {
           //做基本变量访问
            if(assignExpr == nullptr)
            {
                switch(pSym->type)
                {
                    case EXPR_STRING:
                    {
                        ExprValue ret;
                        ret.type = EXPR_STRING;

                        if(!isRefGet)
                        {
                            FillExprBySymNode(&ret,pSym,ctx);
                        }
                        else
                        {
                            ret.value.vpoint = pSym->value.vpoint;
                        }

                        return ret;
                    }
                    case EXPR_U16STRING:
                    {
                        ExprValue ret;
                        ret.type = EXPR_U16STRING;

                        if (!isRefGet)
                        {
                            FillExprBySymNode(&ret, pSym, ctx);
                        }
                        else
                        {
                            ret.value.vpoint = pSym->value.vpoint;
                        }

                        return ret;
                    }
                }
            }
            else
            {
                //直接赋值
                FillSymNodeByExpr(pSym,*assignExpr, ctx,true,op);
                return 0;
            }
        }
        else if( listIndex.size() == 1) //字符串的[]访问
        {
            if(op != EQUAL_ASSIGN)
            {
                QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3[%4] 是字符类型，不支持 += -= 等操作！").arg(curLine).arg(curStatement)
                        .arg(QStr(varName)).arg(QStr(listIndex.at(0)->getText()));
                        AbortException(msg);
            }
            int index = -1;
            ExprValue expr = std::any_cast<ExprValue>(visit(listIndex.at(0)->expr()));
            if(expr.type == EXPR_INT)
            {
                index = expr.value.vint;
            }

           //做基本变量访问
            if(assignExpr == nullptr)
            {
                switch(pSym->type)
                {
                    case EXPR_STRING:
                    {
                        ExprValue ret;
                        ret.type = EXPR_CHAR;
                        QByteArray* pByte =  (QByteArray*)pSym->value.vpoint;
                        if(index >= 0 && index < pByte->size())
                        {
                            ret.value.vchar = pByte->at(index);
                        }
                        else
                        {
                            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                    .arg(QStr(varName)).arg(pByte->size()).arg(index);
                            AbortException(msg);
                        }

                        return ret;
                    }
                    case EXPR_U16STRING:
                    {
                        ExprValue ret;
                        ret.type = EXPR_WCHAR;

                        QString* pByte =  (QString*)pSym->value.vpoint;
                        if(index >= 0 && index < pByte->size())
                        {
                            ret.value.vwchar = pByte->at(index).unicode();
                        }
                        else
                        {
                            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                    .arg(QStr(varName)).arg(pByte->size()).arg(index);
                            AbortException(msg);
                        }

                        return ret;
                    }
                }
            }
            else
            {
                //直接赋值
                //FillSymNodeByExpr(pSym,*assignExpr, ctx,true,op);
                if(EXPR_STRING == pSym->type && assignExpr->type == EXPR_CHAR)
                {
                    QByteArray* pByte =  (QByteArray*)pSym->value.vpoint;
                    if(index >= 0 && index < pByte->size())
                    {
                        pByte->operator [](index) = assignExpr->value.vchar;
                    }
                    else
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                .arg(QStr(varName)).arg(pByte->size()).arg(index);
                        AbortException(msg);
                    }
                }
                else if(EXPR_U16STRING == pSym->type)
                {
                    QString* pByte =  (QString*)pSym->value.vpoint;
                    if(index >= 0 && index < pByte->size())
                    {
                        if(assignExpr->type == EXPR_WCHAR)
                        {
                            pByte->operator [](index) = QChar(assignExpr->value.vwchar);
                        }
                        else if(assignExpr->type == EXPR_CHAR)
                        {
                            pByte->operator [](index) = QChar(assignExpr->value.vchar);
                        }
                        else if(assignExpr->type == EXPR_INT)
                        {
                            if(assignExpr->value.vint >= 0 && assignExpr->value.vint <= 65535)
                            {
                                pByte->operator [](index) = QChar(assignExpr->value.vint);
                            }
                            else
                            {
                                QString msg = QString(u8"错误：行号 %1 语句 %2 宽字符使用整数合法赋值范围是0-65535，赋值是%3 无效越界 ").arg(curLine).arg(curStatement)
                                        .arg(assignExpr->value.vint);
                                AbortException(msg);
                            }
                        }
                        else
                        {
                            QString msg = QString(u8"错误：行号 %1 语句 %2 宽字符合法赋值类型是字符、宽字符、整数。当前赋值类型是 %3").arg(curLine).arg(curStatement)
                                    .arg(getExpeTypeValue(assignExpr->type));
                            AbortException(msg);
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 下标访问越界，%3 长度是 %4, 下标值是 %5").arg(curLine).arg(curStatement)
                                .arg(QStr(varName)).arg(pByte->size()).arg(index);
                        AbortException(msg);
                    }
                }
                return 0;
            }
        }
        else
        {
            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3[%4] 已经是字符类型，后续[]访问无效！").arg(curLine).arg(curStatement)
                    .arg(QStr(varName)).arg(QStr(listIndex.at(0)->getText()));
                    AbortException(msg);
            return 0;
        }
    }
    break;

    case EXPR_BOOL:
    case EXPR_CHAR:
    case EXPR_WCHAR:
    case EXPR_INT:
    case EXPR_INT64:
    case EXPR_FLOAT:
    case EXPR_STRUCT_DEC:
    case EXPR_DATE:
    case EXPR_FILE:
    case EXPR_EXCEL:
    {


        //变量本身是基本变量，则不能有列表自动或结构体表达
        if(listIndex.size() != 0 || pStMem != nullptr)
        {
            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 是 %4 ,非法或未知求值或访问语句 %5, 变量 %3 不能进行 [] 或 . 操作访问！ ").arg(curLine).arg(curStatement)
                    .arg(QStr(varName)).arg(getVarTypeNameByName(varName)).arg(QStr(ctx->getText()));
            AbortException(msg);
        }



       //做基本变量访问
        if(assignExpr == nullptr)
        {
            switch(pSym->type)
            {
                case EXPR_STRING:
                {
                    ExprValue ret;
                    ret.type = EXPR_STRING;

                    if(!isRefGet)
                    {
                        FillExprBySymNode(&ret,pSym,ctx);
                    }
                    else
                    {
                        ret.value.vpoint = pSym->value.vpoint;
                    }

                    return ret;
                }
                case EXPR_U16STRING:
                {
                    ExprValue ret;
                    ret.type = EXPR_U16STRING;

                    if (!isRefGet)
                    {
                        FillExprBySymNode(&ret, pSym, ctx);
                    }
                    else
                    {
                        ret.value.vpoint = pSym->value.vpoint;
                    }

                    return ret;
                }
                case EXPR_STRUCT_DEC:
                {
                    //是结构体描述本身。
                    ExprValue ret;
                    ret.type = EXPR_STRUCT_DEC;

                    if (!isRefGet)
                    {
                        FillExprBySymNode(&ret, pSym, ctx);
                    }
                    else
                    {
                        ret.value.vpoint = pSym->value.vpoint;
                    }

                    return ret;
                }
            case EXPR_DATE:
            {
                ExprValue ret;
                ret.type = EXPR_DATE;

                if(!isRefGet)
                {
                    FillExprBySymNode(&ret,pSym,ctx);
                }
                else
                {
                    ret.value.vpoint = pSym->value.vpoint;
                }

                return ret;

            }
            case EXPR_FILE:
            {

                ExprValue ret;
                ret.type = EXPR_FILE;

                //文件和列表一样，都是浅拷贝。但是还是有区分，使用引用返回时isRefGet=true时，不增加内部的计数。修改为统一都增加，外部统一释放。
                //否则导致外部没法释放。
                //ret.value.vpoint = pSym->value.vpoint;
                if(!isRefGet)
                {
                    FillExprBySymNode(&ret,pSym,ctx);
                }
                else
                {
                    ret.value.vpoint = pSym->value.vpoint;
                    addListMapRefNum(ret.value.vpoint);
                }

                return ret;
            }
                break;
            case EXPR_EXCEL:
            {

                ExprValue ret;
                ret.type = EXPR_EXCEL;

                //文件和列表一样，都是浅拷贝。但是还是有区分，使用引用返回时isRefGet=true时，不增加内部的计数。修改为统一都增加，外部统一释放。
                //否则导致外部没法释放。
                //ret.value.vpoint = pSym->value.vpoint;
                if (!isRefGet)
                {
                    FillExprBySymNode(&ret, pSym, ctx);
                }
                else
                {
                    ret.value.vpoint = pSym->value.vpoint;
                    addListMapRefNum(ret.value.vpoint);
                }

                return ret;

            }
            break;
                default:
                {
                    //其它基本变量没有浅拷贝的说法,因为已经是基本变量了
                    ExprValue ret;
                    ret.type = pSym->type;

                    FillExprBySymNode(&ret,pSym,ctx);

                    return ret;
                }
            }
        }
        else
        {
            //直接赋值
            FillSymNodeByExpr(pSym,*assignExpr, ctx,true,op);
            return 0;
        }
    }
        break;



    case EXPR_STRUCT:
    {
        if(listIndex.size() != 0)
        {
            QString msg = QString(u8"错误：行号 %1 语句 %2 变量 %3 是 %4 ,非法的求值或访问语句 %5 ").arg(curLine).arg(curStatement)
                    .arg(QStr(varName)).arg(getExpeTypeValue(pSym->type)).arg(QStr(ctx->getText()));
        }

        //分结构体本身还是结构体成员变量
        if(pStMem != nullptr)
        {

            STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
            int index = getMemIndexFromStruct(pValue->structType, pStMem->getText(),ctx);
            if(index != -1)
            {
                //ExprValue ret;
                //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                ExprValue* pRet = pVec->at(index);

                //20250215 pinvar加入时间和文件后，结构体中也可以是时间和文件，这里最开始只考虑了字符串，还需要补充时间和文件的逻辑。
                //把文件也是作为基本变量来考虑，但是文件是引用计数来考虑的。

                if(assignExpr == nullptr)
                {
                    //分值拷贝和引用返回两种情况。特别注意，下同。
                    if(!isRefGet)
                    {
                        return pRet->deepCopy();
                    }

                    //这里有些不好理解，如果是结构，则引用返回的是一个浅拷贝副本，这里要注意，这个副本，如果类型是文件、字符串，则
                    //副本和元素对象是公用内存的。但如果是其它基本类型，则就是一个完全的副本。所以外面如果做a++这样的操作，针对基本类型是会失败的
                    //因为返回的是副本。要注意这里的概念，下同。

                    //这里返回的可能是文件，所以也要加一下引用。不如会漏掉。
                    addListMapRefNum(*pRet);
                    return *pRet;
                }
                else
                {
                    //直接赋值
                    FillExprByExpr(pRet,assignExpr,ctx,true,op);
                    return 0;
                }

            }
            else
            {
                QString msg= QString(u8"错误：行号 %1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pStMem->getText()));
                AbortException(msg);
            }


            return 0;
        }
        else
        {
            if(assignExpr == nullptr)
            {


                if(!isRefGet)
                {
                    //结构体必须深拷贝
                    STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
                    ExprValue ret;
                    ret.type = EXPR_STRUCT;
                    ret.value.vpoint = pValue->deepCopy();
                    return ret;
                }
                ExprValue ret;
                ret.type = EXPR_STRUCT;
                ret.value.vpoint = pSym->value.vpoint;
                return ret;
            }
            else
            {
               FillSymNodeByExpr(pSym,*assignExpr, ctx,true,op);
                return 0;
            }
        }

    }
        break;
    case EXPR_LIST:
    {

            std::string listName = varName;

            PinParser::StMemVarContext* pMem = ctx->stMemVar();

            std::vector<PinParser::ListindexContext *> indexVec = ctx->listindex();

            //最开始是第一层列表，依次深入
            std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;

            for(int i=0,c=indexVec.size(); i<c; ++i)
            {
                ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                //必须是整数类型.INT64不行。
                if(ev.type == EXPR_INT)
                {
                    //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                    int index = ev.value.vint;

                    if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                    {
                        ExprValue* ev = pchildlist->at(index);

                        //还需要继续往下剥,而且还能继续剥
                        if(ev->type == EXPR_LIST && (i< (c-1)))
                        {
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                            continue;
                        }
                       /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                        {
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                            AbortException(msg);
                        }*/
                        else if(i == (c-1)) //不需要继续往下剥
                        {
                            if(pMem == nullptr)
                            {
                                if(assignExpr == nullptr)
                                {


                                    //如果是列表，做浅拷贝返回。其余深拷贝,所谓深拷贝，文件还是浅拷贝特例。
                                    if(ev->type == EXPR_LIST || isRefGet)
                                    {

                                        addListMapRefNum(*ev);

                                        return *ev;
                                    }
                                    else
                                    {
                                        return ev->deepCopy();
                                    }
                                }
                                else
                                {
                                    //直接赋值
                                    FillExprByExpr(ev,assignExpr,ctx,true,op);
                                    return 0;
                                }
                            }
                            else
                            {
                                //继续访问结构体
                                if(ev->type == EXPR_STRUCT)
                                {
                                    STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                    int index = getMemIndexFromStruct(pValue->structType, pMem->getText(), ctx);
                                    if(index != -1)
                                    {
                                        //ExprValue ret;
                                        //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                        std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                        ExprValue* ret = pVec->at(index);
                                        //这里不能调用ret.freeMem,否则会破坏结构体中的原始值。
                                        //这里返回的ret,其实是一个原始结构体中的一个副本，所以不能调用ret.freeMem。另外就是返回给外面的时候
                                        //需要做一个深拷贝。


                                        if(assignExpr == nullptr)
                                        {
                                            //返回值，做深拷贝。
                                            if(!isRefGet)
                                            {
                                                return ret->deepCopy();
                                            }
                                            addListMapRefNum(*ret);
                                            return *ret;
                                        }
                                        else
                                        {
                                            FillExprByExpr(ret,assignExpr,ctx,true,op);
                                            return 0;
                                        }

                                    }
                                    else
                                    {
                                        QString msg= QString(u8"错误：行号%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                        AbortException(msg);
                                    }
                                }
                                else
                                {
                                    QString msg = QString(u8"错误：行号 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(curLine).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                    AbortException(msg);
                                }
                            }

                        }
                        else
                        {
                            QString msg = QString(u8"错误：行号 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(curLine).arg(curStatement).arg(QStr(listName)).arg(i);
                            AbortException(msg);
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(curLine).arg(curStatement).arg(index);
                        AbortException(msg);
                    }
                }
                else
                {
                    QString msg = QString(u8"错误：行号 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(curLine).arg(curStatement).arg(i);
                    AbortException(msg);
                }
            }

            //直接访问列表，不能加.mem 方式。列表一定是引用，没存在深拷贝的说法。
            if(indexVec.size() == 0 && pMem == nullptr)
            {


                if(assignExpr == nullptr)
                {
                    ExprValue ret;
                    ret.type = EXPR_LIST;

                    //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
                    ret.value.vpoint = pchildlist;
                    addListMapRefNum(ret.value.vpoint);

                    return ret;
                }
                else
                {

                    FillSymNodeByExpr(pSym, *assignExpr, ctx,true,op);
                }
            }
            else if(indexVec.size() == 0 && pMem != nullptr)
            {
                QString msg = QString(u8"错误：行号  %1 语句 %2 列表不是结构体，无法访问成员变量 %3 !").arg(curLine).arg(curStatement).arg(QStr(pMem->getText()));
                AbortException(msg);
            }

            //其余返回错误
            return 0;

    }
        break;
    case EXPR_MAP:
        {
            std::string mapName = varName;

            PinParser::StMemVarContext* pMem = ctx->stMemVar();

            std::vector<PinParser::ListindexContext *> indexVec = ctx->listindex();

            //最开始是第一层列表，依次深入
            std::unordered_map<ExprValue, ExprValue*>* pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)pSym->value.vpoint;
            std::vector<ExprValue*>* pchildlist = nullptr;

            int i = 0;
            std::string curkey;

            for(int c=indexVec.size(); i<c; ++i)
            {
                ExprValue key = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                //必须是整数类型.INT INT64 或 字符串
                //if(key.type == EXPR_INT || key.type == EXPR_INT64 || key.type == EXPR_STRING)
                if(key.isMapKeyType())
                {

                    if(pchildmap != nullptr)
                    {
                        ExprValue* ev = nullptr;

                        auto it = pchildmap->find(key);

                        //找到
                        if(it != pchildmap->end())
                        {
                            key.freeMem();

                            ev = it->second;

                            //还需要继续往下剥,而且还能继续剥
                            if(ev->type == EXPR_MAP && (i< (c-1)))
                            {
                                //这里就是开始解开列表，往里面一层一层的剥列表
                                pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)ev->value.vpoint;
                                continue;
                            }
                            else if(ev->type == EXPR_LIST)
                            {
                                //特殊情况，遇到列表了
                                //这里就是开始解开列表，往里面一层一层的剥列表
                                //跳出map，开始解列表
                                curkey = indexVec.at(i)->expr()->getText();
                                pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                                break;
                            }
                            else if(i == (c-1)) //不需要继续往下剥
                            {
                                if(pMem == nullptr)
                                {
                                    if(assignExpr == nullptr)
                                    {


                                        //如果是列表或map，做浅拷贝返回。其余深拷贝
                                        if(ev->type == EXPR_LIST || ev->type == EXPR_MAP || isRefGet)
                                        {

                                            addListMapRefNum(*ev);

                                            return *ev;
                                        }
                                        else
                                        {
                                            return ev->deepCopy();
                                        }
                                    }
                                    else
                                    {
                                        FillExprByExpr(ev,assignExpr,ctx,true,op);
                                        return 0;
                                    }
                                }
                                else
                                {
                                    //继续访问结构体
                                    if(ev->type == EXPR_STRUCT)
                                    {
                                        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                        int index = getMemIndexFromStruct(pValue->structType, pMem->getText(), ctx);
                                        if(index != -1)
                                        {
                                            //ExprValue ret;
                                            //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                            std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                            ExprValue* ret = pVec->at(index);



                                            if(assignExpr == nullptr)
                                            {
                                                if(!isRefGet)
                                                {
                                                    return ret->deepCopy();
                                                }
                                                addListMapRefNum(*ret);
                                                return *ret;
                                            }
                                            else
                                            {
                                                FillExprByExpr(ret,assignExpr,ctx,true,op);
                                                return 0;
                                            }

                                        }
                                        else
                                        {
                                            QString msg= QString(u8"错误：行号 %1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(curLine).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                            AbortException(msg);
                                        }
                                    }
                                    else
                                    {
                                        QString msg = QString(u8"错误：行号 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(curLine).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                        AbortException(msg);
                                    }
                                }

                            }
                        }
                        //没有找到map的key
                        else
                        {
                        QString msg = QString(u8"错误：行号 %1 语句 %2 字典没有关键字key %3 ").arg(curLine).arg(curStatement).arg(QStr(indexVec.at(i)->expr()->getText()));
                        AbortException(msg);
                        }
                    }
                }
                else
                {
                    QString msg = QString(u8"错误：行号 %1 语句 %2 字典%3 访问元素第 %4 个关键字 %5 类型错误，字典关键字索引只能是整数或字符串类型!").arg(curLine).arg(curStatement).arg(QStr(mapName)).arg(i).arg(QStr(indexVec.at(i)->expr()->getText()));
                    AbortException(msg);
                }
            }

            //遇到列表访问
            if(pchildlist != nullptr)
            {
                ++i;//继续解访问后面的列表

                int listStart = i;
                //最开始是第一层列表，依次深入
               for(int c=indexVec.size(); i<c; ++i)
                {
                    ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                    //必须是整数类型.INT64不行。
                    if(ev.type == EXPR_INT)
                    {
                        //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                        int index = ev.value.vint;

                        if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                        {
                            ExprValue* ev = pchildlist->at(index);

                            //还需要继续往下剥,而且还能继续剥
                            if(ev->type == EXPR_LIST && (i< (c-1)))
                            {
                                //这里就是开始解开列表，往里面一层一层的剥列表
                                pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                                continue;
                            }
                           /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                            {
                                //这里就是开始解开列表，往里面一层一层的剥列表
                                QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                                AbortException(msg);
                            }*/
                            else if(i == (c-1)) //不需要继续往下剥
                            {
                                if(pMem == nullptr)
                                {

                                    if(assignExpr == nullptr)
                                    {


                                        //如果是列表，做浅拷贝返回。其余深拷贝
                                        if(ev->type == EXPR_LIST ||  isRefGet)
                                        {

                                            addListMapRefNum(*ev);

                                            return *ev;
                                        }
                                        else
                                        {
                                            return ev->deepCopy();
                                        }
                                    }
                                    else
                                    {
                                        FillExprByExpr(ev,assignExpr,ctx,true,op);
                                        return 0;
                                    }
                                }
                                else
                                {
                                    //继续访问结构体
                                    if(ev->type == EXPR_STRUCT)
                                    {
                                        STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                        int index = getMemIndexFromStruct(pValue->structType, pMem->getText(), ctx);
                                        if(index != -1)
                                        {
                                            //ExprValue ret;
                                            //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                            std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                            ExprValue* ret = pVec->at(index);

                                            if(assignExpr == nullptr)
                                            {


                                                if(!isRefGet)
                                                {
                                                    return ret->deepCopy();
                                                }
                                                addListMapRefNum(*ret);
                                                return *ret;
                                            }
                                            else
                                            {
                                                FillExprByExpr(ret,assignExpr,ctx,true,op);
                                                return 0;
                                            }

                                        }
                                        else
                                        {
                                            QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(pMem->getText()));
                                            AbortException(msg);
                                        }
                                    }
                                    else
                                    {
                                        QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                        AbortException(msg);
                                    }
                                }

                            }
                        else
                        {
                                QString msg = QString(u8"错误：函数 %1 语句 %2 字典值的多层列表非法范围，字典 %3 关键字 %4 对应值，其第 %5 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(curkey)).arg(i-listStart);
                                AbortException(msg);
                            }
                        }
                        else
                        {
                            QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                            AbortException(msg);
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                        AbortException(msg);
                    }
                }

                //走到这里，说明前面没有走for循环，
                //直接访问列表，不能加.mem 方式，因为必定返回列表，而不是结构体
                if(pMem == nullptr)
                {
                    if(assignExpr == nullptr)
                    {



                    ExprValue ret;
                    ret.type = EXPR_LIST;

                    //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
                    ret.value.vpoint = pchildlist;
                    addListMapRefNum(ret.value.vpoint);
                    return ret;
                    }
                    else
                    {
                        FillSymNodeByExpr(pSym, *assignExpr, ctx,true,op);
                        return 0;
                    }
                }
                else if(pMem != nullptr)
                {
                    QString msg = QString(u8"错误：函数 %1 语句 %2 列表不是结构体，无法访问成员变量 %3 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMem->getText()));
                    AbortException(msg);
                }


            }

            //直接访问字典，不能加.mem 方式
            if(pMem == nullptr)
            {
                if(assignExpr == nullptr)
                {


                    ExprValue ret;
                    ret.type = EXPR_MAP;

                    //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
                    ret.value.vpoint = pchildmap;
                    addListMapRefNum(ret.value.vpoint);
                    return ret;
                }
                else
                {
                    FillSymNodeByExpr(pSym, *assignExpr, ctx,true,op);
                    return 0;
                }
            }
            else if(pMem != nullptr)
            {
                QString msg = QString(u8"错误：函数 %1 语句 %2 字典不是结构体，无法访问成员变量 %3 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMem->getText()));
                AbortException(msg);
            }

            //其余返回错误
            return 0;

        }

        break;

        //20250302 当函数名称可以随意VARNAME保存一致后,函数必须也做变量可用。在参数传递中可使用。
        //但是函数只在参数传递中可使用，其它地方暂时不允许。？？后续也可放开，看是否需要太灵活。
    case EXPR_FUN:
    case EXPR_CALL_BACK_FUN:
    {


        ExprValue ret;
        ret.type = EXPR_FUN;
        ret.varName = &(pSym->name);

        if (!isRefGet)
        {
            ret.value.vpoint = new std::string(*(std::string*)pSym->value.vpoint);//就是函数名称，而且只能是全局函数
#ifdef PIN_MEM_REF
            newTime();
#endif
        }
        else
        {
            ret.value.vpoint = pSym->value.vpoint;
        }


        return ret;
    }
        break;

    default:
        break;
    }
    ExprValue ret;
    return ret;
#if 0
    //如果是字符串变量。
    if(ctx->basevar() != nullptr && ctx->basevar()->STRING() != nullptr)
    {
        std::string varName = ctx->basevar()->STRING()->getText();

        SymNode* pSym = getVarFromSymTable(varName, ctx);

        if(pSym)
        {
            ExprValue ret;
            ret.type = EXPR_STRING;

            if(!isRefGet)
            {
                FillExprBySymNode(&ret,pSym,ctx);
            }
            else
            {
                ret.value.vpoint = pSym->value.vpoint;
            }

            return ret;
        }
        return 0;

    }
    //结构体中的某个成员变量
    else if(ctx->structMem())
    {
        std::string stName = ctx->structMem()->STRUCT_ID()->getText();

        SymNode* pSym = getVarFromSymTable(stName, ctx);

        if(pSym)
        {
            STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
            int index = getMemIndexFromStruct(pValue->structType, ctx->structMem()->stMemVar()->getText());
            if(index != -1)
            {
                //ExprValue ret;
                //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                ExprValue* pRet = pVec->at(index);

                //20250215 pinvar加入时间和文件后，结构体中也可以是时间和文件，这里最开始只考虑了字符串，还需要补充时间和文件的逻辑。
                //把文件也是作为基本变量来考虑，但是文件是引用计数来考虑的。
#if 0
                //这里不能调用ret.freeMem,否则会破坏结构体中的原始值。
                if(ret.type == EXPR_STRING)
                {
                    //必须要深拷贝一下，外面会释放这个
                    QByteArray* pNew = new QByteArray(*(QByteArray*)ret.value.vpoint);
                    ret.value.vpoint = pNew;
                    #ifdef PIN_MEM_REF
            newTime();
#endif
                }
#endif
                //分值拷贝和引用返回两种情况。特别注意，下同。
                if(!isRefGet)
                {
                    return pRet->deepCopy();
                }

                //这里有些不好理解，如果是结构，则引用返回的是一个浅拷贝副本，这里要注意，这个副本，如果类型是文件、字符串，则
                //副本和元素对象是公用内存的。但如果是其它基本类型，则就是一个完全的副本。所以外面如果做a++这样的操作，针对基本类型是会失败的
                //因为返回的是副本。要注意这里的概念，下同。

                //这里返回的可能是文件，所以也要加一下引用。不如会漏掉。
                addListMapRefNum(*pRet);
                return *pRet;

            }
            else
            {
                QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(ctx->structMem()->stMemVar()->getText()));
                AbortException(msg);
            }

        }
        return 0;
    }
    else if(ctx->STRUCT_ID())
    {
        //整个结构体做变量，而不是结构体的某个成员变量
        std::string stName = ctx->STRUCT_ID()->getText();

        SymNode* pSym = getVarFromSymTable(stName, ctx);

        if(pSym)
        {
#if 0
            //这里没有做深拷贝，所以对结构体表达式访问时，会直接修改结构体。
            //需要配合起来。freeMem里面，暂时不对结构体做释放。
            STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
            ExprValue ret;
            ret.type = EXPR_STRUCT;
            ret.value.vpoint = pValue;
            return ret;
#endif
            //分值拷贝和引用返回两种情况。特别注意，下同。
            if(!isRefGet)
            {
                //结构体必须深拷贝
                STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)pSym->value.vpoint;
                ExprValue ret;
                ret.type = EXPR_STRUCT;
                ret.value.vpoint = pValue->deepCopy();
                return ret;
            }
            ExprValue ret;
            ret.type = EXPR_STRUCT;
            ret.value.vpoint = pSym->value.vpoint;
            return ret;
        }
        else
        {
            QString msg= QString(u8"错误：函数%1 语句 %2 找不到结构体变量 %3，该变量没有定义!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(stName));
            AbortException(msg);
        }
        return 0;
    }
    else if(ctx->accesslist() != nullptr) //列表中的某个成员
    {
        std::string listName = ctx->accesslist()->LIST_ID()->getText();

        PinParser::AccesslistContext* pList = ctx->accesslist();

        PinParser::StMemVarContext* pMem = pList->stMemVar();

        SymNode* pSym = getVarFromSymTable(listName, ctx);

        std::vector<PinParser::ListindexContext *> indexVec = pList->listindex();

        //最开始是第一层列表，依次深入
        std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;

        for(int i=0,c=indexVec.size(); i<c; ++i)
        {
            ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
            //必须是整数类型.INT64不行。
            if(ev.type == EXPR_INT)
            {
                //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                int index = ev.value.vint;

                if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                {
                    ExprValue* ev = pchildlist->at(index);

                    //还需要继续往下剥,而且还能继续剥
                    if(ev->type == EXPR_LIST && (i< (c-1)))
                    {
                        //这里就是开始解开列表，往里面一层一层的剥列表
                        pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                        continue;
                    }
                   /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                    {
                        //这里就是开始解开列表，往里面一层一层的剥列表
                        QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                        AbortException(msg);
                    }*/
                    else if(i == (c-1)) //不需要继续往下剥
                    {
                        if(pMem == nullptr)
                        {
                            //如果是列表，做浅拷贝返回。其余深拷贝
                            if(ev->type == EXPR_LIST || isRefGet)
                            {

                                addListMapRefNum(*ev);

                                return *ev;
                            }
                            else
                            {
                                return ev->deepCopy();
                            }
                        }
                        else
                        {
                            //继续访问结构体
                            if(ev->type == EXPR_STRUCT)
                            {
                                STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                if(index != -1)
                                {
                                    //ExprValue ret;
                                    //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                    std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                    ExprValue* ret = pVec->at(index);
                                    //这里不能调用ret.freeMem,否则会破坏结构体中的原始值。
                                    //这里返回的ret,其实是一个原始结构体中的一个副本，所以不能调用ret.freeMem。另外就是返回给外面的时候
                                    //需要做一个深拷贝。

                                    //返回值，做深拷贝。
                                    if(!isRefGet)
                                    {
                                        return ret->deepCopy();
                                    }
                                    addListMapRefNum(*ret);
                                    return *ret;

                                }
                                else
                                {
                                    QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(ctx->structMem()->stMemVar()->getText()));
                                    AbortException(msg);
                                }
                            }
                            else
                            {
                                QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                AbortException(msg);
                            }
                        }

                    }
                    else
                    {
                        QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                        AbortException(msg);
                    }
                }
                else
                {
                    QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                    AbortException(msg);
                }
            }
            else
            {
                QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                AbortException(msg);
            }
        }

        //直接访问列表，不能加.mem 方式。列表一定是引用，没存在深拷贝的说法。
        if(indexVec.size() == 0 && pMem == nullptr)
        {
            ExprValue ret;
            ret.type = EXPR_LIST;

            //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
            ret.value.vpoint = pchildlist;
            addListMapRefNum(ret.value.vpoint);

            return ret;
        }
        else if(indexVec.size() == 0 && pMem != nullptr)
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 列表不是结构体，无法访问成员变量 %3 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMem->getText()));
            AbortException(msg);
        }

        //其余返回错误
        return 0;

    }
    else if(ctx->accessmap() != nullptr) //map中的某个成员
    {
        std::string mapName = ctx->accessmap()->MAP_ID()->getText();

        PinParser::AccessmapContext* pMap = ctx->accessmap();

        PinParser::StMemVarContext* pMem = pMap->stMemVar();

        SymNode* pSym = getVarFromSymTable(mapName, ctx);

        std::vector<PinParser::ListindexContext *> indexVec = pMap->listindex();

        //最开始是第一层列表，依次深入
        std::unordered_map<ExprValue, ExprValue*>* pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)pSym->value.vpoint;
        std::vector<ExprValue*>* pchildlist = nullptr;

        int i = 0;
        std::string curkey;

        for(int c=indexVec.size(); i<c; ++i)
        {
            ExprValue key = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
            //必须是整数类型.INT INT64 或 字符串
            if(key.type == EXPR_INT || key.type == EXPR_INT64 || key.type == EXPR_STRING)
            {

                if(pchildmap != nullptr)
                {
                    ExprValue* ev = nullptr;

                    auto it = pchildmap->find(key);

                    //找到
                    if(it != pchildmap->end())
                    {
                        key.freeMem();

                        ev = it->second;

                        //还需要继续往下剥,而且还能继续剥
                        if(ev->type == EXPR_MAP && (i< (c-1)))
                        {
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            pchildmap = (std::unordered_map<ExprValue, ExprValue*>*)ev->value.vpoint;
                            continue;
                        }
                        else if(ev->type == EXPR_LIST)
                        {
                            //特殊情况，遇到列表了
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            //跳出map，开始解列表
                            curkey = indexVec.at(i)->expr()->getText();
                            pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                            break;
                        }
                        else if(i == (c-1)) //不需要继续往下剥
                        {
                            if(pMem == nullptr)
                            {
                                //如果是列表或map，做浅拷贝返回。其余深拷贝
                                if(ev->type == EXPR_LIST || ev->type == EXPR_MAP || isRefGet)
                                {

                                    addListMapRefNum(*ev);

                                    return *ev;
                                }
                                else
                                {
                                    return ev->deepCopy();
                                }
                            }
                            else
                            {
                                //继续访问结构体
                                if(ev->type == EXPR_STRUCT)
                                {
                                    STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                    int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                    if(index != -1)
                                    {
                                        //ExprValue ret;
                                        //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                        std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                        ExprValue* ret = pVec->at(index);

                                        if(!isRefGet)
                                        {
                                            return ret->deepCopy();
                                        }
                                        addListMapRefNum(*ret);
                                        return *ret;

                                    }
                                    else
                                    {
                                        QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(ctx->structMem()->stMemVar()->getText()));
                                        AbortException(msg);
                                    }
                                }
                                else
                                {
                                    QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                    AbortException(msg);
                                }
                            }

                        }
                    }//没有找到map的key
                    else
                    {
                        QString msg = QString(u8"错误：函数 %1 语句 %2 字典没有关键字key %3 ").arg(getCurFunQSName()).arg(curStatement).arg(QStr(indexVec.at(i)->expr()->getText()));
                        AbortException(msg);
                    }
                }
            }
            else
            {
                QString msg = QString(u8"错误：函数 %1 语句 %2 字典%3 访问元素第 %4 个关键字 %5 类型错误，字典关键字索引只能是整数或字符串类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(i).arg(QStr(indexVec.at(i)->expr()->getText()));
                AbortException(msg);
            }
        }

        //遇到列表访问
        if(pchildlist != nullptr)
        {
            ++i;//继续解访问后面的列表

            int listStart = i;
            //最开始是第一层列表，依次深入
           for(int c=indexVec.size(); i<c; ++i)
            {
                ExprValue ev = std::any_cast<ExprValue>(visit(indexVec.at(i)->expr()));
                //必须是整数类型.INT64不行。
                if(ev.type == EXPR_INT)
                {
                    //std::vector<ExprValue*>* pchildlist = (std::vector<ExprValue*>*)pSym->value.vpoint;
                    int index = ev.value.vint;

                    if(pchildlist != nullptr && index >=0 && index < pchildlist->size())
                    {
                        ExprValue* ev = pchildlist->at(index);

                        //还需要继续往下剥,而且还能继续剥
                        if(ev->type == EXPR_LIST && (i< (c-1)))
                        {
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            pchildlist = (std::vector<ExprValue*>*)ev->value.vpoint;
                            continue;
                        }
                       /* else if(ev->type != EXPR_LIST && (i< (c-1))) //还需要继续往下剥,但是已经不是列表了保存
                        {
                            //这里就是开始解开列表，往里面一层一层的剥列表
                            QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表非法范围，列表 %3 第 %4 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(listName)).arg(i);
                            AbortException(msg);
                        }*/
                        else if(i == (c-1)) //不需要继续往下剥
                        {
                            if(pMem == nullptr)
                            {
                                //如果是列表，做浅拷贝返回。其余深拷贝
                                if(ev->type == EXPR_LIST ||  isRefGet)
                                {

                                    addListMapRefNum(*ev);

                                    return *ev;
                                }
                                else
                                {
                                    return ev->deepCopy();
                                }
                            }
                            else
                            {
                                //继续访问结构体
                                if(ev->type == EXPR_STRUCT)
                                {
                                    STRUCT_VALUE_DATA* pValue = (STRUCT_VALUE_DATA*)ev->value.vpoint;
                                    int index = getMemIndexFromStruct(pValue->structType, pMem->getText());
                                    if(index != -1)
                                    {
                                        //ExprValue ret;
                                        //把第n个元素的结构返回。这里是否需要释放呢？这里需要深拷贝，如果是string，得重新拷贝
                                        std::vector<ExprValue*>* pVec = (std::vector<ExprValue*>*)pValue->pValue;

                                        ExprValue* ret = pVec->at(index);


                                        if(!isRefGet)
                                        {
                                            return ret->deepCopy();
                                        }
                                        addListMapRefNum(*ret);
                                        return *ret;

                                    }
                                    else
                                    {
                                        QString msg= QString(u8"错误：函数%1 语句 %2 结构体 %3 没有成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pValue->structType)).arg(QStr(ctx->structMem()->stMemVar()->getText()));
                                        AbortException(msg);
                                    }
                                }
                                else
                                {
                                    QString msg = QString(u8"错误：函数 %1 语句 %2 列表第 %3 个序列元素不是结构体类型，无法访问成员变量 %4 !").arg(getCurFunQSName()).arg(curStatement).arg(i).arg(QStr(pMem->getText()));
                                    AbortException(msg);
                                }
                            }

                        }
                        else
                        {
                            QString msg = QString(u8"错误：函数 %1 语句 %2 字典值的多层列表非法范围，字典 %3 关键字 %4 对应值，其第 %5 层元素，已经不是列表类型!").arg(getCurFunQSName()).arg(curStatement).arg(QStr(mapName)).arg(QStr(curkey)).arg(i-listStart);
                            AbortException(msg);
                        }
                    }
                    else
                    {
                        QString msg = QString(u8"错误：函数 %1 语句 %2 多层列表访问元素第 %3 个序号类型错误，列表越界或不是列表类型的非法访问!").arg(getCurFunQSName()).arg(curStatement).arg(index);
                        AbortException(msg);
                    }
                }
                else
                {
                    QString msg = QString(u8"错误：函数 %1 语句 %2 列表访问元素第 %3 个序号类型错误，列表索引只能是int32 整数类型!").arg(getCurFunQSName()).arg(curStatement).arg(i);
                    AbortException(msg);
                }
            }

            //走到这里，说明前面没有走for循环，
            //直接访问列表，不能加.mem 方式，因为必定返回列表，而不是结构体
            if(pMem == nullptr)
            {
                ExprValue ret;
                ret.type = EXPR_LIST;

                //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
                ret.value.vpoint = pchildlist;
                addListMapRefNum(ret.value.vpoint);
                return ret;
            }
            else if(pMem != nullptr)
            {
                QString msg = QString(u8"错误：函数 %1 语句 %2 列表不是结构体，无法访问成员变量 %3 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMem->getText()));
                AbortException(msg);
            }


        }

        //直接访问字典，不能加.mem 方式
        if(pMem == nullptr)
        {
            ExprValue ret;
            ret.type = EXPR_MAP;

            //注意这里不是深拷贝，所以不能随便释放。freeMem中不会对列表进行自动释放。
            ret.value.vpoint = pchildmap;
            addListMapRefNum(ret.value.vpoint);
            return ret;
        }
        else if(pMem != nullptr)
        {
            QString msg = QString(u8"错误：函数 %1 语句 %2 字典不是结构体，无法访问成员变量 %3 !").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMem->getText()));
            AbortException(msg);
        }

        //其余返回错误
        return 0;

    }
    else if(ctx->FILE_ID() != nullptr)
    {
        //文件不用说了，只有浅拷贝方式。
        std::string varName = ctx->FILE_ID()->getText();

        SymNode* pSym = getVarFromSymTable(varName, ctx);

        if(pSym)
        {
            ExprValue ret;
            ret.type = EXPR_FILE;

            //文件和列表一样，都是浅拷贝。但是还是有区分，使用引用返回时isRefGet=true时，不增加内部的计数。修改为统一都增加，外部统一释放。
            //否则导致外部没法释放。
            //ret.value.vpoint = pSym->value.vpoint;
            if(!isRefGet)
            {
                FillExprBySymNode(&ret,pSym,ctx);
            }
            else
            {
                ret.value.vpoint = pSym->value.vpoint;
                addListMapRefNum(ret.value.vpoint);
            }

            return ret;
        }
        return 0;
    }
    else if(ctx->DATE_ID() != nullptr)
    {
        //
        std::string varName = ctx->DATE_ID()->getText();

        SymNode* pSym = getVarFromSymTable(varName, ctx);

        if(pSym)
        {
            ExprValue ret;
            ret.type = EXPR_DATE;

            if(!isRefGet)
            {
                FillExprBySymNode(&ret,pSym,ctx);
            }
            else
            {
                ret.value.vpoint = pSym->value.vpoint;
            }

            return ret;
        }
        return 0;
    }
    //其它基本变量没有浅拷贝的说法。
    else
    {
        return visitChildren(ctx);
    }
#endif
}

//访问列表。注意：列表表达式每次访问到，都是把空间生成在堆上面的。
//所以如果外面的表达式使用完毕以后，是需要释放的。需要使用内存引用计数来管理才行。
std::any ExprVisitor::visitList(PinParser::ListContext *ctx)
{
    std::vector<PinParser::ElementContext *> eleVec = ctx->element();

    ExprValue ret;
    ret.type = EXPR_LIST;

    if(!eleVec.empty())
    {

        //因为值可能是结构体，所以这里使用ExprValue*
        std::vector<ExprValue*>* pData = new std::vector<ExprValue*>(eleVec.size());
#ifdef PIN_MEM_REF
            newTime();
#endif
        //最外面的这层地址，也要加入引用计数
        addListMapRefNum(pData);

        ret.value.vpoint = pData;

        for(int i=0, c = eleVec.size(); i <c ;++i)
        {
            if(eleVec.at(i)->expr() != nullptr || eleVec.at(i)->stRightVar() != nullptr)
            {
                //deepMoveCopy类似movd拷贝函数，把value mode拷贝出来入栈。
                //20250129 特别注意：这里value返回的可能还是一个列表，所以value里面的指针，就是指向原始列表的地址。但是value本身是一个独立的对象
                //所以当调用deepMoveCopy的时候，本质是返回一个value的拷贝，而且该返回拷贝对象的指针，还是指向原始列表的地址。
                //这里是没问题的，因为作为赋值表达式的右边值，不存在被修改的可能。只有左值才可能修改，但是左值一定保证深拷贝。
                ExprValue value = std::any_cast<ExprValue>(visit(eleVec.at(i)));
                (*pData)[i] = value.shallowMoveCopy();

                //value.freeMem();因为是move拷贝，现在value已经被掏空，可以不用释放。
            }
            else if(eleVec.at(i)->list()!= nullptr)
            {
                //递归
                ExprValue value = std::any_cast<ExprValue>(visitList(eleVec.at(i)->list()));

                //内层的列表，必须要加入引用计数，因为第一次初始化时，外面无法直接访问，所以外面是没有引用计数管理的。但这些列表真实存在。
                //addListMapRefNum(value.value.vpoint);

                (*pData)[i] = value.shallowMoveCopy();

                //value.freeMem();因为是move拷贝，现在value已经被掏空，可以不用释放。

                //不需要addListMapRefNum，value里面已经有，这里没有释放value,等于是已经有计数

            }
        }

        return ret;
    }
    else
    {
        //空的就是空的，但是还分配空间
        std::vector<ExprValue*>* pData = new std::vector<ExprValue*>();
		#ifdef PIN_MEM_REF
            newTime();
#endif
        ret.value.vpoint = pData;
        addListMapRefNum(pData);
    }

    return ret;
}


//访问字典，字典的值可能是字典，还可能是列表。列表的元素不能是字典。
std::any ExprVisitor::visitMap(PinParser::MapContext *ctx)
{
    std::vector<PinParser::MapelementContext *> eleVec = ctx->mapelement();

    ExprValue ret;
    ret.type = EXPR_MAP;

    //因为值可能是结构体或列表，所以这里使用ExprValue*
    std::unordered_map<ExprValue, ExprValue*>* pData = new std::unordered_map<ExprValue, ExprValue*>();
    ret.value.vpoint = pData;
#ifdef PIN_MEM_REF
            newTime();
#endif
    //和列表一样，这个外面接收的变量会加入引用计数，所以这里先不加计数。都必须加入。
        addListMapRefNum(pData);

        if(!eleVec.empty())
        {

            for(int i=0, c = eleVec.size(); i <c ;++i)
            {
                PinParser::MapelementContext* pMapkv = eleVec.at(i);

                const ExprValue keyExpr = std::any_cast<ExprValue>(visit(pMapkv->mapkey()->expr()));

                //key是否类型合法
                if(keyExpr.type == EXPR_INT || keyExpr.type == EXPR_STRING || keyExpr.type == EXPR_INT64)
                {
                    //ok
                }
                else
                {
                    QString msg = QString(u8"错误：函数 %1 语句 %2 字典类型表达式 %3 不是整数或字符串，无法做字典的关键字！").arg(getCurFunQSName()).arg(curStatement).arg(QStr(pMapkv->mapkey()->expr()->getText()));
                    AbortException(msg);
                    return 0;
                }

                ExprValue value = std::any_cast<ExprValue>(visit(pMapkv->rightvar()));

                //这里是入map的地方，是浅拷贝，加入计数。浅拷贝不用调用value.free
                //只有list map才会加入计数，其余类型不会。
                //addListMapRefNum(value); value没释放，加减持平，不需要

                pData->insert({keyExpr,value.shallowMoveCopy()});


#if 0
                if(pMapkv->rightvar()->expr() != nullptr)
                {
                    //expr返回可能是列表、结构体，字典。这里要特别注意，其实和列表类似。
                    ExprValue value = std::any_cast<ExprValue>(visit(pMapkv->rightvar()->expr()));
                    (*pData)[keyExpr] = value.shallowMoveCopy();
                    //value.freeMem();因为是move拷贝，现在value已经被掏空，可以不用释放。下同
                }
                else if(pMapkv->rightvar()->list() != nullptr)
                {
                    ExprValue value = std::any_cast<ExprValue>(visit(pMapkv->rightvar()->list()));
                    pData->insert({keyExpr,value.shallowMoveCopy()});
                }
                else if(pMapkv->rightvar()->map() != nullptr)
                {
                    ExprValue value = std::any_cast<ExprValue>(visit(pMapkv->rightvar()->map()));
                    pData->insert({keyExpr,value.shallowMoveCopy()});
                }
#endif
            }
        }
        return ret;

}


//列表或字典 以 lb_1[id] = JG_INFO{1,2,3};的方式。只能作为赋值语句的右值部分。
std::any ExprVisitor::visitStRightVar(PinParser::StRightVarContext *ctx)
{
    std::string stTypeName = ctx->VARNAME()->getText();
    std::vector<PinParser::ExprContext *> exprVec = ctx->expr();

    //结构体是在全局中
    SymNode* pStType = getVarFromGlobalSymTable(stTypeName,ctx,1);

    ExprValue ret;
    ret.type = EXPR_STRUCT;

    //看看结构体的参数和赋值参数能否匹配
    std::vector<std::string>* paraList =  (std::vector<std::string>*)(pStType->value.vpoint);
    int paraNum = paraList->size()/2;

    STRUCT_VALUE_DATA* pdata = new STRUCT_VALUE_DATA();
	#ifdef PIN_MEM_REF
            newTime();
#endif

    pdata->structType = stTypeName;
    std::vector<ExprValue*>* pNew = new std::vector<ExprValue*>(paraNum);
	#ifdef PIN_MEM_REF
            newTime();
#endif

    pdata->pValue = pNew;
    ret.value.vpoint = pdata;


    if(paraNum == exprVec.size())
    {
        //开始逐一赋值结构体变量。
        for(int i=0,c=exprVec.size(); i<c; ++i)
        {
            ExprValue ev = std::any_cast<ExprValue>(visit(exprVec.at(i)));

            //如果类型相等，则直接赋值
            int type = getVarTypeByName(paraList->at(i+paraNum));
            if(type == ev.type)
            {
                //直接浅拷贝即可。这里不能调用ev.free,因为浅拷贝到容器中去了
                //(*pNew)[i] = ev;
               // FillExprByExpr((*pNew)[i],&ev,ctx);
                (*pNew)[i] = ev.shallowMoveCopy();
            }
            else if(exprTypeMatch(type, ev.type) >= 0)
            {
                //虽然类型不相等，但是可以转换
                //把原来的释放。
                ExprValue temp;
                temp.type = type;
                FillExprByExpr(&temp, &ev, ctx);
                 (*pNew)[i] = temp.shallowMoveCopy();

            }
            else
            {
                QString msg = QString(u8"错误：行号 %1 语句 %2 结构体第%3个变量 %4 参数是 %5，赋值类型是%6, 类型无法匹配！").arg(curLine).arg(curStatement).arg(i+1).arg(QStr(paraList->at(i)))
                        .arg(getExpeTypeValue(type)).arg(getExpeTypeValue(ev.type));
                AbortException(msg);
            }

        }
        return ret;
    }
    else
    {
        QString msg = QString(u8"错误：行号 %1 语句 %2 结构体 %3 声明和定义的形式语句 %4 无法匹配").arg(curLine).arg(curStatement).arg(QStr(stTypeName)).arg(QStr(ctx->getText()));
        AbortException(msg);
    }

    return ret;
}

//把函数的执行结果，作为表达式返回。此时只能有一个返回值，如果函数有多个返回值，则忽略后续的返回值，只返回第一个值。
std::any ExprVisitor::visitCallFunExpr(PinParser::CallFunExprContext* ctx)
{
    //以关心函数返回值的方式执行函数。
    visitRealCallFun(ctx->realCallFun(), nullptr, NEED_RETURN);

    //执行完毕后，取出函数的返回值
    QList<SymNode*>* retList = getcurFunReturnValue();

    if (retList == nullptr || retList->size() == 0)
    {
        //可能是链式调用，目前不清楚调用到了哪一个级别。后续还有继续改进。
        std::string funName = ctx->realCallFun()->getText();

        /*if (ctx->realCallFun()->VARNAME() != nullptr)
        {
            funName = ctx->realCallFun()->VARNAME()->getText();
        }
        else if (ctx->realCallFun()->memberFunAccess() != nullptr)
        {
            if(ctx->realCallFun()->multiCallFun().size() == 0)
            {
                funName = ctx->realCallFun()->memberFunAccess()->getText();
            }
            else
            {
                funName = ctx->realCallFun()->getText();
            }
        }*/

        QString msg = QString(u8"错误：行号 %1 语句 %2 调用函数部分 %3 无返回值，其返回值无法做表达式进一步操作，比如打印输出或给其它变量赋值等！").arg(curLine).arg(curStatement).arg(QStr(funName));
        AbortException(msg);
    }

    //取出第一个，做返回值
    ExprValue ret;
    ret.type = retList->at(0)->type;
    FillExprBySymNode(&ret, retList->at(0),ctx);

    //销毁返回值
    for (int i = 0, c = retList->size(); i < c; ++i)
    {
        retList->at(i)->destory();
        delete retList->at(i);

        #ifdef PIN_MEM_REF
                    freeTimes++;
        #endif
    }
    delete retList;
    #ifdef PIN_MEM_REF
            freeTimes++;
    #endif
    setcurFunReturnValue(nullptr);

    return ret;
}

//位取反
std::any ExprVisitor::visitLogRevExpr(PinParser::LogRevExprContext* ctx)
{
    PinParser::RevVarContext* pExpr = ctx->revVar();

    ExprValue ret;

    ExprValue leftExpr = std::any_cast<ExprValue>(visit(pExpr));

    if (leftExpr.type == EXPR_INT)
    {
        ret.type = EXPR_INT;

        ret.value.vint = ~(leftExpr.value.vint);
    }
    else if (leftExpr.type == EXPR_INT64)
    {
        ret.type = EXPR_INT64;

        ret.value.vint64 = ~(leftExpr.value.vint64);
    }
    else
    {
        QString msg = QString(u8"错误类型进行 ~ 位取反计算：行号 %1 语句 %2 表达式不是整数类型，无法进行位操作！").arg(curLine).arg(curStatement);
        AbortException(msg);

    }
    leftExpr.freeMem();
    return ret;
}


std::any ExprVisitor::visitLogAndExpr(PinParser::LogAndExprContext* ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT;
            ret.value.vint = (leftExpr.value.vint & rightExpr.value.vint);
        }
        else if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint & rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 & rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 & rightExpr.value.vint);
        }
        else
        {
            QString msg = QString(u8"错误类型进行 & 位并且计算：行号 %1 语句 %2 表达式不是整数类型，无法进行位操作！").arg(curLine).arg(curStatement);
            AbortException(msg);

        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

std::any ExprVisitor::visitLogOrExpr(PinParser::LogOrExprContext* ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT;
            ret.value.vint = (leftExpr.value.vint | rightExpr.value.vint);
        }
        else if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint | rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 | rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 | rightExpr.value.vint);
        }
        else
        {
            QString msg = QString(u8"错误类型进行 & 位或计算：行号 %1 语句 %2 表达式不是整数类型，无法进行位操作！").arg(curLine).arg(curStatement);
            AbortException(msg);

        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

std::any ExprVisitor::visitLogXorExpr(PinParser::LogXorExprContext* ctx)
{
    std::vector<PinParser::ExprContext*> exprVec = ctx->expr();

    ExprValue ret;
    ret.type = EXPR_ERR;

    if (exprVec.size() == 2)
    {
        ExprValue leftExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));
        ExprValue rightExpr = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT;
            ret.value.vint = (leftExpr.value.vint ^ rightExpr.value.vint);
        }
        else if (leftExpr.type == EXPR_INT && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint ^ rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT64)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 ^ rightExpr.value.vint64);
        }
        else if (leftExpr.type == EXPR_INT64 && rightExpr.type == EXPR_INT)
        {
            ret.type = EXPR_INT64;
            ret.value.vint64 = (leftExpr.value.vint64 ^ rightExpr.value.vint);
        }
        else
        {
            QString msg = QString(u8"错误类型进行 ^ 位异或计算：行号 %1 语句 %2 表达式不是整数类型，无法进行位操作！").arg(curLine).arg(curStatement);
            AbortException(msg);

        }

        leftExpr.freeMem();
        rightExpr.freeMem();
    }

    return ret;
}

//单语句调用，比如直接写 zjs_1; lb_1;啥也不干，必须要手动释放下，否则自动求值导致变量不释放
std::any ExprVisitor::visitSignalState(PinParser::SignalStateContext *ctx)
{

//#ifdef PIN_DEBUG
   // QString msg = QString(u8"警告: 行号 %1 孤独语句 %2 可能是无用功语句，请留意！如无用，建议删除，避免做无用功！").arg(curLine).arg(curStatement);

    //std::cout << msg.toStdString() << std::endl;
//#endif

    ExprValue expr = std::any_cast<ExprValue>(visit(ctx->expr()));

    expr.freeMem();

    return 0;
}

#if 0
std::any ExprVisitor::visitBasevar(PinParser::BasevarContext* ctx)
{
    std::string varName = ctx->getText();
    SymNode* pSym = getVarFromSymTable(varName, ctx);

    if (pSym != nullptr)
    {
        ExprValue expr;
        expr.type = pSym->type;

        FillExprBySymNode(&expr, pSym, ctx);
        return expr;
    }
    //
    return nullptr;
}
#endif

std::any ExprVisitor::visitPinFlag(PinParser::PinFlagContext *ctx)
{
    std::string flag = ctx->PIN_STATIC_FLAG()->getText();

    ExprValue ret;
    ret.type = EXPR_INT;
    ret.value.vint = 0;

    if (flag.size() < 2)
    {
        return ret;
    }
    char *firstChar = flag.data();

    const char* rawPtr = flag.data() + 5;

    int code = (rawPtr[0] << 8) | (rawPtr[1]);

    if(firstChar[0] == 'P')
    {
    switch (code)
    {
        case ('U' << 8 | 'T'):
        {
            if(flag == "Pin::UTF8" || flag == "Pin::UTF-8")
            {
                ret.value.vint = CODE_ID::UTF8_NOBOM;
            }
            else if(flag == "Pin::UTF16-LE")
            {
                ret.value.vint = CODE_ID::UNICODE_LE;
            }
            else if(flag == "Pin::UTF16-BE")
            {
                ret.value.vint = CODE_ID::UNICODE_BE;
            }
        }
        break;

        case ('G' << 8 | 'B'):
        {
            ret.value.vint = CODE_ID::GBK;
        }
            break;

        case ('B' << 8 | 'i'):
        {
            ret.value.vint = CODE_ID::BIG5;
        }
            break;

        case ('E' << 8 | 'U'):
        {
            if(flag == "Pin::EUC-JP")
            {
                ret.value.vint = CODE_ID::EUC_JP;
            }
            else if(flag == "Pin::EUC-KR")
            {
                ret.value.vint = CODE_ID::EUC_KR;
            }
        }
            break;

        case ('S' << 8 | 'h'):
        {
            ret.value.vint = CODE_ID::Shift_JIS;
        }
            break;

        case ('K' << 8 | 'O'):
        {
            ret.value.vint = CODE_ID::KOI8_R;
        }
            break;

        case ('T' << 8 | 'S'):
        {
            ret.value.vint = CODE_ID::TSCII;
        }
            break;

        case ('T' << 8 | 'I'):
        {
            ret.value.vint = CODE_ID::TIS_620;
        }
            break;

        case ('I' << 8 | 'B'):
        {
            ret.value.vint = CODE_ID::IBM866;
        }
            break;

        case ('l' << 8 | 'i'): //line
        {
            ret.value.vint = curLine;
        }
        break;

        case ('f' << 8 | 'u'): //fun
        {
            ret.type = EXPR_STRING;
            ret.setString(getCurFunName());
        }
        break;

        case ('C' << 8 | 'a')://CaseSens
        {
            ret.type = EXPR_INT;
            ret.value.vint = 1; //
        }
        break;

        case ('N' << 8 | 'o')://Noxxx
        {
            ret.type = EXPR_INT;
            ret.value.vint = 0;

            char nextChar = rawPtr[2];

            switch (nextChar)
            {
            case 'C':
                ret.value.vint = 0; //NoCaseSens
                break;
            case 'S':
                ret.value.vint = (int)(QDir::NoSymLinks);//NoSymLinks
                break;
            case 'D':
                ret.value.vint = (int)(QDir::NoDotAndDotDot);//NoDotAndDotDot
                break;
            case 'F'://NoFilter
                ret.value.vint = 0;//NoFilter 没有任何选项。
                break;


            default:
                break;
            }
        }
        break;

        case ('B' << 8 | 'a')://Base64Encode
        {
            if(flag == "Pin::Base64Encode")
            {
                ret.value.vint = 0;
            }
            else if(flag == "Pin::Base64UrlEncode")
            {
                ret.value.vint = 1;
            }
            else
            {
                ret.type = EXPR_ERR;
            }
        }
        break;

        case ('K' << 8 | 'e')://KeepTrailingEquals
        {
            ret.type = EXPR_INT;
            ret.value.vint = 0;
        }
        break;

        case ('O' << 8 | 'm')://OmitTrailingEquals
        {
            ret.type = EXPR_INT;
            ret.value.vint = 2;
        }
        break;

        case ('I' << 8 | 'g')://IgnoreDecodeErrors
        {
            ret.type = EXPR_INT;

            if (rawPtr[6] == 'D')//IgnoreDecodeErrors
            {
                ret.value.vint = 0;
            }
            else if (rawPtr[6] == 'C')//IgnoreCase
            {
                ret.value.vint = QDir::IgnoreCase;
            }
        }
        break;

        case ('A' << 8 | 'b')://AbortOnDecodeErrors
        {
            ret.type = EXPR_INT;
            ret.value.vint = 4;
        }
        break;

        //以下是文件目录变量过滤选项
        case ('D' << 8 | 'i')://Dirs
        {
            ret.type = EXPR_INT;

            /*if (flag == "Pin::Dirs")
            {
                ret.value.vint = QDir::Dirs;
            }
            else */if (flag == "Pin::DirsFirst")
            {
                ret.value.vint = QDir::DirsFirst;
            }
            else if (flag == "Pin::DirsLast")
            {
                ret.value.vint = QDir::DirsLast;
            }
            else
            {
                ret.type = EXPR_ERR;
            }
        }
        break;
        case ('A' << 8 | 'l')://AllDirs
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::AllDirs;
        }
        break;
        case ('F' << 8 | 'i')://Files
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Files;
        }
        break;
        //case ('D' << 8 | 'r')://Drivers
        //{
        //    ret.type = EXPR_INT;
        //    ret.value.vint = QDir::Drives;
        //}
        //break;

        case ('R' << 8 | 'e')://Readable
        {
            ret.type = EXPR_INT;

            if (rawPtr[2] == 'a')
            {
                ret.value.vint = QDir::Readable;
            }
            else if (rawPtr[2] == 'v') //Reversed
            {
                ret.value.vint = QDir::Reversed;
            }
        }
        break;
        case ('W' << 8 | 'r')://Writable
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Writable;
        }
        break;
        case ('E' << 8 | 'x')://Executable
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Executable;
        }
        break;
        case ('M' << 8 | 'o')://Modified
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Modified;
        }
        break;
        case ('H' << 8 | 'i')://Hidden
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Hidden;
        }
        break;
        case ('S' << 8 | 'y')://System
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::System;
        }
        break;

        //排序
        case ('N' << 8 | 'a')://Name
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Name;
        }
        break;

        case ('T' << 8 | 'i')://Name
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Time;
        }
        break;

        case ('S' << 8 | 'i')://Size
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Size;
        }
        break;

        case ('T' << 8 | 'y')://Type
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDir::Type;
        }
        break;

        case ('B' << 8 | 'o')://BottomUp 自底向上os.walk
        {
            ret.type = EXPR_INT;
            ret.value.vint = QDIR_WALK_BottomUp; //目前看起来是空闲的。
    }
        break;


    }
    }
    else if(firstChar[0] == 'R')
    {
        switch (code)
        {
        case ('N' << 8 | 'o'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::NoPatternOption;
        }
            break;
        case ('C' << 8 | 'a'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::CaseInsensitiveOption;
        }
            break;

        case ('D' << 8 | 'o'):
        {
            ret.type = EXPR_INT;
             if (rawPtr[2] == 't')
             {
                ret.value.vint = QRegularExpression::DotMatchesEverythingOption;
             }
             else if (rawPtr[2] == 'n')
             {
                ret.value.vint = QRegularExpression::DontCaptureOption;
             }

        }
            break;

        case ('M' << 8 | 'u'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::MultilineOption;
        }
            break;

        case ('E' << 8 | 'x'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::ExtendedPatternSyntaxOption;
        }
            break;
        case ('I' << 8 | 'n'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::InvertedGreedinessOption;
        }
            break;

        case ('U' << 8 | 's'):
        {
            ret.type = EXPR_INT;
            ret.value.vint = QRegularExpression::UseUnicodePropertiesOption;
        }
            break;

        }
    }
    return ret;

}

//遍历目录。类似python的os.walk
std::any ExprVisitor::visitForwalk(PinParser::ForwalkContext *ctx)  {

    //先求表达式
    std::vector<PinParser::ExprContext *> exprVec = ctx->expr();


    if(exprVec.size() > 3 || exprVec.size() == 0)
    {
        QString err = QString(u8"错误：行号 %1 语句 %2 walk 函数最多接收3个参数，当前有 %3 个参数，请检查!").arg(curLine).arg(curOnelineSrcStatement)
                .arg(exprVec.size());
        AbortException(err);
    }


    QString dirPath;

    //默认就是不带.. 和 . 还有 符号链接的。符号链接容易死循环。
    QDir::Filters filter = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks;
    QDir::SortFlags sortFlags = QDir::NoSort; //默认不排序。

    //第1个是需要变量的文件夹名称
    if(exprVec.size() >= 1)
    {
        ExprValue dirExpr = std::any_cast<ExprValue>(visit(exprVec.at(0)));

        if(dirExpr.type == EXPR_STRING)
        {
            //必须是字符串。
            dirPath = QString::fromStdString(dirExpr.getString());
        }
        else if(dirExpr.type == EXPR_U16STRING)
        {
            dirPath = *(dirExpr.getU16String());
        }
        else
        {
            QString err = QString(u8"错误：行号 %1 语句 %2 walk的目录路径只能是字符串类型，而 %3 是 %4").arg(curLine).arg(curOnelineSrcStatement)
                    .arg(QStr(exprVec.at(0)->getText())).arg(getExpeTypeValue(dirExpr.type,&dirExpr));
            AbortException(err);
        }
        dirExpr.freeMem();

        QFileInfo fi(dirPath);
        if(fi.isFile() || !fi.exists())
        {
            QString err = QString(u8"错误：行号 %1 语句 %2 变量%3 的目录路径 %4 不存在，或者不是一个目录，无法遍历！请检查!\n如果路径字符串存在反斜杠，请转义或使用裸字符串。").arg(curLine).arg(curOnelineSrcStatement)
                    .arg(QStr(exprVec.at(0)->getText())).arg(dirPath);
            AbortException(err);
        }

        //如果是相对路径，修改为绝对路径
        if(fi.isRelative())
        {
            dirPath = fi.absoluteFilePath();
        }
    }

    //第2个是遍历的参数。必须是整数
    if(exprVec.size() >= 2)
    {
        ExprValue walkMode = std::any_cast<ExprValue>(visit(exprVec.at(1)));

        if(walkMode.type == EXPR_INT)
        {
            //为了避免死循环，默认只能继续加参数，不能去掉QDir::NoDotAndDotDot | QDir::NoSymLinks;
            filter |= (QDir::Filters)walkMode.value.vint;
        }
        else
        {
            QString err = QString(u8"错误：行号 %1 语句 %2 walk的选项只能是整数类型，而 %3 是 %4").arg(curLine).arg(curOnelineSrcStatement)
                    .arg(QStr(exprVec.at(1)->getText())).arg(getExpeTypeValue(walkMode.type,&walkMode));
            AbortException(err);
        }
        walkMode.freeMem();
    }

    //第3个是遍历的排序参数。必须是整数
    if(exprVec.size() >= 3)
    {
        ExprValue sortMode = std::any_cast<ExprValue>(visit(exprVec.at(2)));

        if(sortMode.type == EXPR_INT)
        {
            //必须是整数。
            sortFlags = (QDir::SortFlags)sortMode.value.vint;
        }
        else
        {
            QString err = QString(u8"错误：行号 %1 语句 %2 walk的排序类型只能是整数类型，而 %3 是 %4").arg(curLine).arg(curOnelineSrcStatement)
                    .arg(QStr(exprVec.at(1)->getText())).arg(getExpeTypeValue(sortMode.type,&sortMode));
            AbortException(err);
        }
        sortMode.freeMem();
    }


    //进入循环
//看到for时，加入一个作用域
    SymNode* node = new SymNode;
#ifdef PIN_MEM_REF
    newTime();
#endif
    node->type = FOR_SCOPE;
    //作用域反而是没有名称的。
    getPinSymTable()->push_back(node);

   //加入三个循环变量
    std::vector<tree::TerminalNode *> varVec = ctx->VARNAME();

        SymNode* nodePath = new SymNode;
    #ifdef PIN_MEM_REF
        newTime();
    #endif
        nodePath->name = varVec.at(0)->getText();
        nodePath->type = EXPR_STRING;
        //作用域反而是没有名称的。
        getPinSymTable()->push_back(nodePath);

        SymNode* nodeDirList = new SymNode;
    #ifdef PIN_MEM_REF
        newTime();
    #endif
        nodeDirList->name = varVec.at(1)->getText();
        nodeDirList->type = EXPR_LIST;
        //作用域反而是没有名称的。
        getPinSymTable()->push_back(nodeDirList);


        SymNode* nodeFileList = new SymNode;
    #ifdef PIN_MEM_REF
        newTime();
    #endif
        nodeFileList->name = varVec.at(2)->getText();
        nodeFileList->type = EXPR_LIST;
        //作用域反而是没有名称的。
        getPinSymTable()->push_back(nodeFileList);


        //使用非递归的方式来做
        //如果没有设置QDIR_WALK_BottomUp,则默认使用自上而下。
        bool topdown = (((int)filter & QDIR_WALK_BottomUp) == 0); //false自下而上。true 则是自上而下,自上而下好理解一些。默认是自上而下。



        //默认使用自上而下，感觉好理解一些。


        QString curRootPath = dirPath;
        QStringList dirList;
        QStringList fileList;

        //所谓自下而上，即是先访问最里面的子目录和其下面的文件
        //自上而下，则先访问当前文件，返回子文件夹，和文件。在逐一访问子文件夹。

        int times = 0;

        //这里先实现自上而下的逻辑。
        QFileInfoList allDirFiList;

        if(topdown)
        {
        while(true)
        {
            //开始遍历目录文件
             QDir dir(curRootPath);
             QFileInfoList curFiList = dir.entryInfoList(filter, sortFlags);


            //遍历当前根目录下面发现的每个文件夹和文件，然后直接返回一次到循环变量。
            for(int i=0, s = curFiList.size(); i<s; ++i)
            {
                //如果是文件夹，则有先处理
                if(curFiList.at(i).isDir())
                {
                    dirList.append(curFiList.at(i).fileName());
                }
                else if(curFiList.at(i).isFile())
                {
                    fileList.append(curFiList.at(i).fileName());
                }
            }

            //第一次完毕后，赋值给外面的三个循环变量
            nodePath->value.vpoint = new QByteArray(curRootPath.toUtf8());
            #ifdef PIN_MEM_REF
                newTime();
            #endif

                std::vector<ExprValue*>* pDirData = (std::vector<ExprValue*>*) new std::vector<ExprValue*>(dirList.size());
#ifdef PIN_MEM_REF
                newTime();
#endif
                QFileInfoList insertToQueue;

                for(int i=0, s = dirList.size(); i < s ; ++i)
                {
                    ExprValue* value = new ExprValue();
#ifdef PIN_MEM_REF
    newTime();
#endif
                    value->type = EXPR_STRING;
                    value->value.vpoint = new QByteArray(dirList.at(i).toUtf8());
                    #ifdef PIN_MEM_REF
                        newTime();
                    #endif

                        pDirData->operator [](i) = value;

                        //把所有目录加入到allDirFiList中，后续要继续访问每个目录。这里一定要使用绝对路径，否则总是容易出错。
                        QFileInfo fi(dir.absolutePath() + QDir::separator() + dirList.at(i));
                        insertToQueue.append(fi); //每个新节点都是有序放入insertToQueue。
                }


                //但是每次发现的新的文件夹，要一次性放入到allDirFiList的头部。
                //这样保证每次新发现的文件，总是先开始访问的。这就是自上而下的思路。
                if(!insertToQueue.isEmpty())
                {
                    for(int i=insertToQueue.size()-1; i>=0; --i)
                    {
                        allDirFiList.push_front(insertToQueue.at(i));
                    }
                }

                nodeDirList->value.vpoint = pDirData;
                addListMapRefNum(pDirData);

                std::vector<ExprValue*>* pFileData = (std::vector<ExprValue*>*) new std::vector<ExprValue*>(fileList.size());
#ifdef PIN_MEM_REF
                newTime();
#endif
                for(int i=0, s = fileList.size(); i < s ; ++i)
                {
                    ExprValue* value = new ExprValue();
#ifdef PIN_MEM_REF
    newTime();
#endif
                    value->type = EXPR_STRING;
                    value->value.vpoint = new QByteArray(fileList.at(i).toUtf8());
                    #ifdef PIN_MEM_REF
                        newTime();
                    #endif

                        pFileData->operator [](i) = value;
                }
                nodeFileList->value.vpoint = pFileData;
                addListMapRefNum(pFileData);


                //完成一次遍历和循环后，开始执行块
                visit(ctx->block());

                //如果是从break中返回，则不继续循环了
                if (getPinRunStatus() == INTO_BREAK)
                {
                    popStatus();
                    break;
                }

                ++times;

                //每1000次调用一下界面，避免卡死。
                if (times > 1000)
                {
                    QCoreApplication::processEvents();
                    times = 0;
                }

                if (getPinRunStatus() == INTO_CONTINUE)
                {
                    popStatus();
                    continue;
                }

                //要进入到下一次访问。
                dirList.clear();
                fileList.clear();

                //没有了
                if(allDirFiList.isEmpty())
                {
                    break;
                }

                //取出第一个目录，继续遍历。要特别注意，这个absoluteFilePath是使用相对当前路径来做的。不是我们需要的。
                //curRootPath = allDirFiList.takeFirst().absoluteFilePath();
                //curRootPath = dir.absolutePath() + QDir::separator() +  allDirFiList.takeFirst().fileName();
                //前面加入时，就使用绝对路径，不使用相对路径。
                curRootPath = allDirFiList.takeFirst().absoluteFilePath();

                nodePath->destory();
                nodeDirList->destory();
                nodeFileList->destory();

        }
        }
        else
        {
            //自底向上
            QStringList stack;
            stack.push_back(curRootPath);

            QList<QString> visited;
            visited.append(curRootPath);

           while (!stack.isEmpty()) {
               QString currentPath = stack.takeLast();
               QDir dir(currentPath);

               if (!dir.exists()) {
                   std::cout  << "Directory does not exist:" << currentPath.toStdString();
                   continue;
               }

               // 获取所有子目录
               QFileInfoList subDirs = dir.entryInfoList(filter,sortFlags);
               for (const QFileInfo &subDirInfo : subDirs) {
                   if (subDirInfo.isDir()) {
                       stack.push_back(subDirInfo.absoluteFilePath());
                       visited.append(subDirInfo.absoluteFilePath()); // 记录访问顺序
                   }
               }
            }

           //现在所有子目录都在visited了。逆序访问每个文件夹即可。
           curRootPath = visited.takeLast(); //一定有一个，不用判空
           while(true)
           {
               //开始遍历目录文件
                QDir dir(curRootPath);
                QFileInfoList curFiList = dir.entryInfoList(filter, sortFlags);


               //遍历当前根目录下面发现的每个文件夹和文件，然后直接返回一次到循环变量。
               for(int i=0, s = curFiList.size(); i<s; ++i)
               {
                   //如果是文件夹，则有先处理
                   if(curFiList.at(i).isDir())
                   {
                       dirList.append(curFiList.at(i).fileName());
                   }
                   else if(curFiList.at(i).isFile())
                   {
                       fileList.append(curFiList.at(i).fileName());
                   }
               }

               //第一次完毕后，赋值给外面的三个循环变量
               nodePath->value.vpoint = new QByteArray(curRootPath.toUtf8());
               #ifdef PIN_MEM_REF
                   newTime();
               #endif

                   std::vector<ExprValue*>* pDirData = (std::vector<ExprValue*>*) new std::vector<ExprValue*>(dirList.size());
   #ifdef PIN_MEM_REF
                   newTime();
   #endif

                   for(int i=0, s = dirList.size(); i < s ; ++i)
                   {
                       ExprValue* value = new ExprValue();
   #ifdef PIN_MEM_REF
       newTime();
   #endif
                       value->type = EXPR_STRING;
                       value->value.vpoint = new QByteArray(dirList.at(i).toUtf8());
                       #ifdef PIN_MEM_REF
                           newTime();
                       #endif

                       pDirData->operator [](i) = value;

                   }


                   nodeDirList->value.vpoint = pDirData;
                   addListMapRefNum(pDirData);

                   std::vector<ExprValue*>* pFileData = (std::vector<ExprValue*>*) new std::vector<ExprValue*>(fileList.size());
   #ifdef PIN_MEM_REF
                   newTime();
   #endif
                   for(int i=0, s = fileList.size(); i < s ; ++i)
                   {
                       ExprValue* value = new ExprValue();
   #ifdef PIN_MEM_REF
       newTime();
   #endif
                       value->type = EXPR_STRING;
                       value->value.vpoint = new QByteArray(fileList.at(i).toUtf8());
                       #ifdef PIN_MEM_REF
                           newTime();
                       #endif

                           pFileData->operator [](i) = value;
                   }
                   nodeFileList->value.vpoint = pFileData;
                   addListMapRefNum(pFileData);


                   //完成一次遍历和循环后，开始执行块
                   visit(ctx->block());

                   //如果是从break中返回，则不继续循环了
                   if (getPinRunStatus() == INTO_BREAK)
                   {
                       popStatus();
                       break;
                   }

                   ++times;

                   //没1000次调用一下界面，避免卡死。
                   if (times > 1000)
                   {
                       QCoreApplication::processEvents();
                       times = 0;
                   }

                   if (getPinRunStatus() == INTO_CONTINUE)
                   {
                       popStatus();
                       continue;
                   }

                   //要进入到下一次访问。
                   dirList.clear();
                   fileList.clear();

                   //没有了
                   if(visited.isEmpty())
                   {
                       break;
                   }

                   //取出第一个目录，继续遍历。要特别注意，这个absoluteFilePath是使用相对当前路径来做的。不是我们需要的。
                   //curRootPath = allDirFiList.takeFirst().absoluteFilePath();
                   //curRootPath = dir.absolutePath() + QDir::separator() +  allDirFiList.takeFirst().fileName();
                   //前面加入时，就使用绝对路径，不使用相对路径。
                   curRootPath = visited.takeLast();

                   nodePath->destory();
                   nodeDirList->destory();
                   nodeFileList->destory();

           }


        }
    deleteCurForScope();

    return 0;
}
